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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C语言实现的Web服务器

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

標(biāo)準(zhǔn)C實(shí)現(xiàn)WEB服務(wù)器

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

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。