日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C语言实现的Web服务器

發布時間:2023/11/27 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C语言实现的Web服务器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
另一篇:

標準C實現WEB服務器

http://blog.sina.com.cn/s/blog_4b73e7600100b02c.html 本文原文地址: http://blog.sina.com.cn/s/blog_4b73e760010007id.html 自己研究了好幾天終于寫出來一個,哈哈,當然也從網上得到了很多的幫助拉。謝謝大家咯!這個版本還不是很完善,但Web服務器的基本框架已經出來了,還有部分的功能需要進行進一步的測試和修改。雖然說C的開發比較慢,對于程序員來說比較難以操作,但通過用C寫這些很底層的東西,可以更好的了解的象java的socket中的工作原理。有一定的幫助! 以下是源代碼: /**************filename: Server.cpp****************
?該程序通過標準socket實現簡單Http服務器
?運行該服務器可以通過瀏覽器訪問服務器目錄下的
?Html文件和jpg圖片 完成初步的Http服務器功能
***************************************************/ #include <winsock.h>
#include <sys/stat.h>
#include <iostream>
using namespace std; #define SERVER_PORT 10000?????????//自定義的服務端口
#define HOSTLEN 256???????????//主機名長度
#define BACKLOG 10???????????//同時等待的連接個數 /**************************************
?該方法包裝了send()
?通過該方法發送數據 能夠全部發出
?沒有遺漏
**************************************/
int sendall(int s, char *buf, int *len) {
?int total = 0;???????????// 已經發送字節數
?int bytesleft = *len;?????????????????????????????????? //還剩余多少字節
?int n;
?while(total < *len) {
??n = send(s, buf+total, bytesleft, 0);
??if (n == -1) { break; }
??total += n;
??bytesleft -= n;
?}
?*len = total;???????????// 返回實際發送出去的字節數
?return n==-1?-1:0;??????????// 成功發送返回0 失敗-1
} /**************************************
?該方法處理錯誤請求
?并向客戶端發送錯誤信息
**************************************/
void wrong_req(int sock) {
?char* error_head = "HTTP/1.0 501 Not Implemented\r\n";?//輸出501錯誤
?int len = strlen(error_head);
?if (sendall(sock, error_head, &len) == -1) {???//向客戶發送
??printf("Sending failed!");
??return;
?}?????? char* error_type = "Content-type: text/plain\r\n";??
?len = strlen(error_type);
?if (sendall(sock, error_type, &len) == -1) {
??printf("Sending failed!");
??return;
?} char* error_end = "\r\n";
?len = strlen(error_end);
?if (sendall(sock, error_end, &len) == -1) {
??printf("Sending failed!");
??return;
?} char* prompt_info = "The command is not yet completed\r\n";
?len = strlen(prompt_info);
?if (sendall(sock, prompt_info, &len) == -1) {
??printf("Sending failed!");
??return;
?}
} /**********************************
?該方法判斷用戶請求的文件是否存在
?不存在返回true 存在返回false
***********************************/
bool not_exit(char* arguments) {
?struct stat dir_info;
?return (stat(arguments, &dir_info) == -1);
} /*************************************
?所請求的文件不存在
*************************************/
void file_not_found(char* arguments, int sock) { char* error_head = "HTTP/1.0 404 Not Found\r\n";???//構造404錯誤head
?int len = strlen(error_head);
?if (sendall(sock, error_head, &len) == -1) {????//向客戶端發送
??printf("Sending error!");
??return;
?}??? char* error_type = "Content-type: text/plain\r\n";
?len = strlen(error_type);
?if (sendall(sock, error_type, &len) == -1) {
??printf("Sending error!");
??return;
?} char* error_end = "\r\n";
?len = strlen(error_end);
?if (sendall(sock, error_end, &len) == -1) {
??printf("Sending error!");
??return;
?} char prompt_info[50] = "Not found:? ";
?strcat(prompt_info, arguments);
?len = strlen(prompt_info);
?if (sendall(sock, prompt_info, &len) == -1) {????//輸出未找到的文件
??printf("Sending error!");
??return;
?}????
} /*************************************
?發送Http協議頭部信息
?其中包括響應類型和Content Type
*************************************/
void send_header(int send_to, char* content_type) {
?
?char* head = "HTTP/1.0 200 OK\r\n";?????//正確的頭部信息
?int len = strlen(head);
?if (sendall(send_to, head, &len) == -1) {???//向連接的客戶端發送數據
??printf("Sending error");
??return;
?} if (content_type) {?????????//content_type不為空
??char temp_1[30] = "Content-type: ";????//準備好要連接的字串
??strcat(temp_1, content_type);?????//構造content_type
??strcat(temp_1, "\r\n");
??len = strlen(temp_1);
??if (sendall(send_to, temp_1, &len) == -1) {
???printf("Sending error!");
???return;
??}
?}
} /***********************************
?取得用戶所請求的文件類型
?即文件后綴 (.html .jpg .gif)
************************************/
char* file_type(char* arg) {
?char * temp;??????????//臨時字符串指針
?if ((temp=strrchr(arg,'.')) != NULL) {????//取得后綴
??return temp+1;
?}
?return "";???????????//如果請求的文件名中沒有. 則返回空串
} /*************************************
?該方法為程序核心
?負責真正發送文件 如*.html *.jpg等
*************************************/
void send_file(char* arguments, int sock) { char* extension = file_type(arguments);????//獲得文件后綴名
?char* content_type = "text/plain";?????//初始化type='text/plain'
?FILE* read_from;?????????//本地文件指針從該文件中讀取.html .jpg等
?int readed = -1;?????????//每次讀得的字節數
?
?if (strcmp(extension, "html") == 0) {????//發送內容為html
??content_type = "text/html";
?} if (strcmp(extension, "gif") == 0) {????//發送內容為gif
??content_type = "image/gif";
?} if (strcmp(extension, "jpg") == 0) {????//發送內容為jpg
??content_type = "image/jpg";
?} read_from = fopen(arguments, "r");?????//打開用戶指定的文件準備讀取
?if(read_from != NULL) {????????//指針不為空
??char read_buf[128];????????//讀文件時的字節緩存數組
??send_header(sock, content_type);????//發送協議頭
??send(sock, "\r\n", 2, 0);??????//再加一個"\r\n" 不能缺少 格式要求 ?while(!feof(read_from)) {??????//判斷文件是否已經結束
???fgets(read_buf, 128, read_from);???//讀取
???int len = strlen(read_buf);
???if (sendall(sock, read_buf, &len) == -1) {?//發送數據
????printf("Sending error!");????//出現發送錯誤顯示到控制臺 繼續發送
????continue;
???}
??}
?}
} /***********************************
?解析并處理用戶請求
***********************************/
void handle_req(char* request, int client_sock) { char command[BUFSIZ];????????//保存解析到的命令字段 GET PUT
?char arguments[BUFSIZ];????????//保存解析到的請求的文件 /*
? * 在用戶請求前加上當前目錄符號
? */
?strcpy(arguments, "./");???????//注意該符號在不同操作系統的區別 /*
? * 解析請求
? */
?if (sscanf(request, "%s%s", command, arguments+2) != 2) {
??return;???????????//解析出錯在返回
?}
?
?printf("handle_cmd:??? %s\n",command);????//向控制臺輸出此時的命令
?printf("handle_path:?? %s\n",arguments);???//向控制臺輸出此時的請求路徑
?
?if (strcmp(command, "GET") != 0) {?????//請求命令格式是否正確
??wrong_req(client_sock);
??return;
?} if (not_exit(arguments)) {???????//請求的文件是否存在??
??file_not_found(arguments, client_sock);
??return;
?} send_file(arguments, client_sock);?????//命令格式及請求路徑正確則發送數據
?
?return;
} /*************************************
?該方法構造服務器端的SOCKET
?返回構造好的socket描述符
*************************************/
int make_server_socket() {
?struct sockaddr_in server_addr;???????//服務器地址結構體 int tempSockId;???????????//臨時存儲socket描述符 tempSockId = socket(PF_INET, SOCK_STREAM, 0);
?
?if (tempSockId == -1) {?????????//如果返回值為-1 則出錯
??return -1;
?} /*
? * 填充服務器連接信息
? */
?server_addr.sin_family = AF_INET;
?server_addr.sin_port = htons(SERVER_PORT);
?server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");??//本地地址
?memset(&(server_addr.sin_zero), '\0', 8); if (bind(tempSockId, (struct sockaddr *)&server_addr,
??sizeof(server_addr)) == -1) {???????//綁定服務如果出錯 則返回-1
??printf("bind error!\n");
??return -1;
?} if (listen(tempSockId, BACKLOG) == -1 ) {?????//開始監聽
??printf("listen error!\n");
??return -1;
?} return tempSockId;???????????//返回取得的SOCKET
} /***********************
?主函數main()
?程序入口
***********************/
void main(int argc, char * argv[]) { /*
? * 調用WSAStartup() 便于訪問sockets library
? */
?WSADATA wsaData; if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
??fprintf(stderr, "WSAStartup failed.\n");
??exit(1);
?} printf("My web server started...\n"); int server_socket;????????//服務器的socket
?int acc_socket;?????????//接收到的用戶連接的socket
?int sock_size = sizeof(struct sockaddr_in);?? struct sockaddr_in user_socket;?????//客戶連接信息 server_socket = make_server_socket();???//創建服務器端的socket if (server_socket == -1) {??????//創建socket出錯
??printf("Server exception!\n");
??exit(2);
?} /*
? *?主循環
? */
?while(true) {
??acc_socket = accept(server_socket, (struct sockaddr *)&user_socket, &sock_size);?//接收連接
??
??//cout << inet_ntoa(user_socket.sin_addr) << endl;??? //測試用:-)//
??
??/*
?? *?讀取客戶請求
?? */
??int numbytes;
??char buf[100];
??if ((numbytes=recv(acc_socket, buf, 99, 0)) == -1) {
???perror("recv");
???exit(1);
??} ?
??//printf("buf ... %s", buf);??????//測試用 ?/*
?? * 處理用戶請求
?? */
??handle_req(buf, acc_socket);
?}
} /**************程序結束Server.cpp******************/

總結

以上是生活随笔為你收集整理的C语言实现的Web服务器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。