C语言写的 mini版的 http 服务器 , 很详细
创始人
2025-01-20 04:33:38
0

文章目录

    • 效果展示
    • 整体架构流程
    • 技术细节
    • 完整代码

效果展示

例如:htpp://192.168.23.140/home.html     ->  正确的请求格式

home.html     这个资源是放在我们服务器里面的 , 并不是随便访问的资源,当然我们可以放很多的资源进去. 

整体架构流程

整个实现的流程其实很简单 , 简单的网络编程基础 , 和对 http 协议格式的基础了解,想要实现并不难.

这里我会对 http协议格式 进行简单的说明.

mini 版的实现 , 我们只处理 客户端发起的 get 请求  ,想要全部实现,还是很有难度的 . 

补充 :

HTTP协议的请求主要包括以下几种:

  1. GET:从服务器获取资源,通常用于请求页面、图片、视频等内容。

  2. POST:向服务器提交数据,通常用于提交表单、上传文件等操作。

  3. PUT:将数据上传到指定的URI,用于更新资源。

  4. DELETE:请求服务器删除指定的资源。

  5. HEAD:类似于GET请求,但服务器只返回请求行和头部,不返回实际内容,用于获取资源的元信息。

  6. OPTIONS:查询支持的HTTP方法,用于确定服务器支持的请求方法。

  7. TRACE:回显服务器收到的请求,用于测试或诊断。

  8. CONNECT:用于代理服务器,将连接转换为隧道。

技术细节

http 协议格式 :  初次基础这个协议的朋友 ,  有一个大概的印象就可以了 , 想要搞明白 http 协议也是相当有难度的  . 

我们这里的实现没有那么复杂.

我们进行收发数据的时候 , 都是一行一行的读取 , 这个很重要 .

每行数据的结尾都有一个明显的标志 , 一个回车符 + 一个换行符

特别注意的是 : 消息报头 和 响应正文  ,  请求头部  和请求数据之间有一个 回车符 + 换行符.

我们在进行数据收发的时候要严格遵循协议的格式.

 常见的错误 : 

提示:实现的模块说明

详细:

  • API 说明

1 . 实现按行读取 , 严格按照 http  格式 , 每一行的尾部是一个  换行符+回车符

是读取到尾部的重要标志

成功返回读取到的字符个数 ,失败返回 -1 

int get_line(int sock , char *buf ,int size ){ 	//每次读取一个字符 	int count = 0 ;   //当前已经读取到的字符大小     char ch = '\0';   	int len = 0 ; 	while( (count < size -1) && ch!='\n'){ 		len  = read(sock , &ch ,1); 		if( len == 1 ){  //正常读取成功 		    //处理 '\r(回车)  \n' 			if( ch=='\r')   continue; 			else if(ch=='\n'){ 				//buf[count] = '\0';     //手动添加字符串结束符 				break; 			} 		//处理一般的字符 		buf[count++] = ch; 		}else if( len < 0 ){   //读取出错的情况 			perror("read fialed\n"); 			count = -1; 			break; 		}else {   //len = 0 的情况   客户端关闭了sock连接 		    fprintf(stderr , "client close\n"); 			count = -1 ; 			break; 		} 	} 	if( count >=0)  buf[count]='\0'; 	//if(Debug)  printf("line information %s\n", buf); 	return count;   }

2 .  处理客户端的请求  . 同时做好防御性编程 , 处理可能发生的情况 . 

实现过程 :   返回值 和 参数 设置都是和主函数中的线程进行匹配.  

读取http请求 +  解析 http 请求 .

都是按照上面 http 协议格式来的 , 如果不记得了 ,可以看看上面. 

void* do_http_request(void* pclient_sock){ 	//读取http请求 	 	//按行读取请求头部 	int len = 0; 	char buf[256]={0}; 	char method[64]={0}; //存放请求方法 	char url[256]={0};//存放url(请求的资源) 	char version[64]={0};//协议版本 	char path[256]={0};//url对应的路径 	int client_sock = *(int *)pclient_sock ;  	 	len = get_line(client_sock , buf ,sizeof(buf) ); 	 	if( len > 0 ){//读取到请求行 		int i=0 , j=0; 		while(!isspace(buf[j]) && i < sizeof(method)-1 ){ 			method[i] = buf[j]; 			i++; 			j++; 		} 		 		method[i] = '\0'; 		if(Debug)   printf("request method = %s\n",method ); 		//判断是否GET方法,这个服务器我们只处理get请求 	    if( strncasecmp( method ,"GET",i)==0 ){ 			if(Debug)   printf("method GET\n"); 			 			//继续读取请求资源 			while(isspace(buf[j++]));//跳过空格 			i = 0; 			while(!isspace(buf[j]) && i < sizeof(url)-1){ 				url[i] = buf[j]; 				i++; 				j++; 			} 			//手动加上字符串结束符 			url[i] = '\0'; 			if(Debug)  printf("request url = %s\n",url); 			//printf("131 : %c\n",buf[j]); 			//读取协议版本 			 			while(isspace(buf[j++]));//跳过空格 			 			i = 0; 			while(!isspace(buf[j]) && i < sizeof(version)-1){ 				version[i] = buf[j]; 				i++; 				j++; 			} 			//手动加上字符串结束符 			version[i] = '\0'; 			if(Debug)  printf("request version = %s\n",version); 			 			//打印请求头部 			do{ 		       len = get_line(client_sock , buf ,sizeof(buf) ); 		       printf("request head = %s\n" , buf ); 	        }while(len > 0); 			 			//****定位到服务器本地的  html文件 **** 			//****如果需要修改资源 , 那么将这里的path 路径改成你自己资源对应的路径**** 			 			//处理 url 中的? 			{ 				char *pos = strchr( url ,'?'); 				if(pos){ 					*pos = '\0'; 					printf("real url= %s\n",url); 				} 				sprintf(path ,"./html_file/%s", url ); 				if(Debug)  printf("path = %s\n", path ); 				 				//判断请求的资源是否存在 ,存在则进行响应 				struct stat st;      //保存文件信息的结构体 				if( stat( path , &st) == -1 ){//如果不存在则响应  404  NOT FOUND 				    fprintf( stderr ," stat :%s failed . reason :%s\n", path , strerror(errno)); 					not_found( client_sock ); 				}else{ //执行http响应 					 					if(S_ISDIR(st.st_mode)){ //如果是一个目录,则补全 						strcat(path , "/indext.html"); 					} 					//响应给客户端 					do_http_response(client_sock , path ); 				} 				 			} 			 		}else{ //客户端的请求方式不是 get  , 响应 501 Method Not Implemented 			fprintf(stderr ,"warning  other method[%s]\n",method); 			do{ 		       len = get_line(client_sock , buf ,sizeof(buf) ); 		       printf("request head = %s\n" , buf ); 	        }while(len > 0); 			//响应客户端 501 Method Not Implemented 			unimplemented(client_sock); 		}	 	}else {   //客户端发送的请求格式有问题 相应 400  BAD REQUEST 		bad_request( client_sock); 	} 	close(client_sock); 	if( pclient_sock )free(pclient_sock); 	return NULL; }

  3 . 将请求的资源,响应给客户端

  注意 :

 我们在将客户端请求的资源发送给客户端的时候 .

在消息报头的最后  我们要还要发送  请求资源的大小( Content-Length:%ld\r\n\r\n ). 

所以说在发送响应的时候 , 一般分两不进行:

- 1. 先发送     状态行 + 消息报头

- 2 . 发送   响应正文

void do_http_response( int client_sock , const char *path ){ 	FILE  *fp = NULL; 	fp = fopen( path ,"rb"); 	if( fp==NULL ){ 		not_found(client_sock); 		return ; 	} 	//文件打开成功 	 	//1. 发送 http 头部  	int ret = header(client_sock , fp); 	 	//2. 发送http body 	if( !ret ){	 		cat(client_sock , fp); 	} 	//3. 清理资源 	fclose( fp ); }

4. 发送 http 头部  (状态行 + 消息报头 )

成功返回 0  失败返回-1

int header(int client_sock ,FILE *fp){ 	char buf[1024] = { 0 }; 	char temp[64]; 	int fpId = -1; 	struct stat st; 	 	strcat(buf , "HTTP/1.1 200 OK\r\n"); 	strcat(buf , "Server:wServer\r\n"); 	strcat(buf , "Content-Type:text/html\r\n"); 	strcat(buf , "Connection:Close\r\n"); 	 	fpId = fileno( fp ); 	if( fstat( fpId ,&st) == -1  ){ 		//响应客户端 500 Internal Server Error 		Internal_Error(client_sock);  		return -1; 	} 	//将响应资源的大小加上 	snprintf( temp , 64 ,"Content-Length:%ld\r\n\r\n" , st.st_size ); 	strcat( buf , temp); 	 	if(Debug) fprintf(stdout ," header :%s\n", buf ); 	 	if( send( client_sock , buf , strlen(buf) , 0 ) < 0 ){ 		fprintf( stderr ," send failed . reason: %s\n", strerror(errno)); 		return -1; 	} 	return 0; }
5. 发送响应资源

因为我们的资源里面包括了图片和音乐

所以在进行文件操作的时候,我们要以二进制的方式进行,

没次读取一个字节.

void cat(int client_sock , FILE *fp){ 	char buf[1024] = { 0 }; 	 	// 1 .没次读取一个字符 	/* 	while( fread(buf , 1 , sizeof(buf), fp) >0 ){ 		int len = write( client_sock , buf , strlen(buf)); 		 		memset( buf , 0 ,sizeof(buf)); 	}*/ 	 	fseek(fp, 0, SEEK_END);     long size = ftell(fp);     fseek(fp, 0, SEEK_SET);      // 为文件分配缓冲区     char* buffer =  (char*)malloc(size);      // 读取文件数据     size_t bytesRead = fread(buffer, 1, size, fp);     if (bytesRead != size) {         printf("读取文件时发生错误\n");        return ;     } 	     // 使用文件数据进行操作...      printf("读取 %lu 字节的数据\n", bytesRead); 	 int len = write( client_sock , buffer , size); 	 if( len < 0){ 		 fprintf(stderr , "write failed . reason :%s\n", strerror(errno)); 	 }         free(buffer); }

好了 ,看到这里这个服务器已经搞定了 ,简单吧 ,核心代码就这么点.

完整版的代码 :   (方便大家复制 , 我给他写在了一个文件里面)

#include #include #include #include #include #include #include #include #include #include  #define SERVER_PORT  80     //服务器的端口号  static int Debug = 1;  //处理http请求 void* do_http_request(void* client_sock);  //返回 -1 表示读取失败   0 表示读取到一个空行  >0 表示读取成功 int get_line(int sock ,char *buf ,int size );  //回复客户端请求 void do_http_response1( int client_sock );  void do_http_response( int client_sock , const char *path );  //响应404 void not_found( int client_sock );  //发送 http 头部  int header(int client_sock ,FILE *fp); 	 //发送http body  void cat(int client_sock , FILE *fp);  //响应501  客户端的请求方式异常 void unimplemented(int client_sock );  //响应400 客户端发送的请求格式有问题 void bad_request( int client_sock );  //500 void Internal_Error(int client_sock);   int main(void){          int sock;//代表信箱     struct sockaddr_in server_addr; //标签,保存端口号,ip地址等      //1, 创建信箱     sock = socket( AF_INET , SOCK_STREAM , 0);          //2. 清空标签,写上地址和端口号     bzero( &server_addr ,sizeof(server_addr));     server_addr.sin_family = AF_INET; //选择协议族IPV4     server_addr.sin_addr.s_addr = htonl( INADDR_ANY ); //监听本地所有ip地址     server_addr.sin_port = htons( SERVER_PORT ); //绑定我们的端口号      //3. 将我们的标签贴到信箱上     bind(sock ,(struct sockaddr *)&server_addr,sizeof(server_addr));      //4. 将我们的信箱挂到传达室,这样,保安就可以接收信件了     listen(sock, 128);    //这里的128表示同时可以接收的信件数量      //万事俱备,只等美女来信     printf("等待美女的来信\n");         int done =1;     //不断接受来信     while( done ){     	struct sockaddr_in client; 		int client_sock,len; 		char client_ip[64]; 		char buff[256]; 		pthread_t id ;   //线程的句柄  		int *pclient_sock=NULL;  		socklen_t client_addr_len; 		client_addr_len = sizeof(client); 		client_sock = accept(sock ,(struct sockaddr *)&client, &client_addr_len);         //打印客户端ip地址和端口号 		printf("client ip: %s\t port : %d\n", 	      inet_ntop( AF_INET, &client.sin_addr.s_addr,client_ip, 		  sizeof(client_ip)), ntohs(client.sin_port)); 	 		//5 、处理http请求 ,读取客户端发送的数据   read() 		//do_http_request(client_sock); 		// 5.1 启动线程实现并发 		pclient_sock = (int *)malloc( sizeof(int)); 		*pclient_sock = client_sock; 		pthread_create( &id ,NULL , do_http_request ,(void *)pclient_sock ); 		 		//6 . 响应客户端请求 		 		//close(client_sock); 		     }     close(sock);     return 0; }  void* do_http_request(void* pclient_sock){ 	//读取http请求 	 	//按行读取请求头部 	int len = 0; 	char buf[256]={0}; 	char method[64]={0}; //存放请求方法 	char url[256]={0};//存放url(请求的资源) 	char version[64]={0};//协议版本 	char path[256]={0};//url对应的路径 	int client_sock = *(int *)pclient_sock ;  	 	len = get_line(client_sock , buf ,sizeof(buf) ); 	 	if( len > 0 ){//读取到请求行 		int i=0 , j=0; 		while(!isspace(buf[j]) && i < sizeof(method)-1 ){ 			method[i] = buf[j]; 			i++; 			j++; 		} 		 		method[i] = '\0'; 		if(Debug)   printf("request method = %s\n",method ); 		//判断是否GET方法,这个服务器我们只处理get请求 	    if( strncasecmp( method ,"GET",i)==0 ){ 			if(Debug)   printf("method GET\n"); 			 			//继续读取请求资源 			while(isspace(buf[j++]));//跳过空格 			i = 0; 			while(!isspace(buf[j]) && i < sizeof(url)-1){ 				url[i] = buf[j]; 				i++; 				j++; 			} 			//手动加上字符串结束符 			url[i] = '\0'; 			if(Debug)  printf("request url = %s\n",url); 			//printf("131 : %c\n",buf[j]); 			//读取协议版本 			 			while(isspace(buf[j++]));//跳过空格 			 			i = 0; 			while(!isspace(buf[j]) && i < sizeof(version)-1){ 				version[i] = buf[j]; 				i++; 				j++; 			} 			//手动加上字符串结束符 			version[i] = '\0'; 			if(Debug)  printf("request version = %s\n",version); 			 			//打印请求头部 			do{ 		       len = get_line(client_sock , buf ,sizeof(buf) ); 		       printf("request head = %s\n" , buf ); 	        }while(len > 0); 			 			//****定位到服务器本地的  html文件 **** 			//****如果需要修改资源 , 那么将这里的path 路径改成你自己资源对应的路径**** 			 			//处理 url 中的? 			{ 				char *pos = strchr( url ,'?'); 				if(pos){ 					*pos = '\0'; 					printf("real url= %s\n",url); 				} 				sprintf(path ,"./html_file/%s", url ); 				if(Debug)  printf("path = %s\n", path ); 				 				//判断请求的资源是否存在 ,存在则进行响应 				struct stat st;      //保存文件信息的结构体 				if( stat( path , &st) == -1 ){//如果不存在则响应  404  NOT FOUND 				    fprintf( stderr ," stat :%s failed . reason :%s\n", path , strerror(errno)); 					not_found( client_sock ); 				}else{ //执行http响应 					 					if(S_ISDIR(st.st_mode)){ //如果是一个目录,则补全 						strcat(path , "/indext.html"); 					} 					//响应给客户端 					do_http_response(client_sock , path ); 				} 				 			} 			 		}else{ //客户端的请求方式不是 get  , 响应 501 Method Not Implemented 			fprintf(stderr ,"warning  other method[%s]\n",method); 			do{ 		       len = get_line(client_sock , buf ,sizeof(buf) ); 		       printf("request head = %s\n" , buf ); 	        }while(len > 0); 			//响应客户端 501 Method Not Implemented 			unimplemented(client_sock); 		}	 	}else {   //客户端发送的请求格式有问题 相应 400  BAD REQUEST 		bad_request( client_sock); 	} 	close(client_sock); 	if( pclient_sock )free(pclient_sock); 	return NULL; }  void do_http_response( int client_sock , const char *path ){ 	FILE  *fp = NULL; 	fp = fopen( path ,"rb"); 	if( fp==NULL ){ 		not_found(client_sock); 		return ; 	} 	//文件打开成功 	 	//1. 发送 http 头部  	int ret = header(client_sock , fp); 	 	//2. 发送http body 	if( !ret ){	 		cat(client_sock , fp); 	} 	//3. 清理资源 	fclose( fp ); }  int header(int client_sock ,FILE *fp){ 	char buf[1024] = { 0 }; 	char temp[64]; 	int fpId = -1; 	struct stat st; 	 	strcat(buf , "HTTP/1.1 200 OK\r\n"); 	strcat(buf , "Server:wServer\r\n"); 	strcat(buf , "Content-Type:text/html\r\n"); 	strcat(buf , "Connection:Close\r\n"); 	 	fpId = fileno( fp ); 	if( fstat( fpId ,&st) == -1  ){ 		//响应客户端 500 Internal Server Error 		Internal_Error(client_sock);  		return -1; 	} 	//将响应资源的大小加上 	snprintf( temp , 64 ,"Content-Length:%ld\r\n\r\n" , st.st_size ); 	strcat( buf , temp); 	 	if(Debug) fprintf(stdout ," header :%s\n", buf ); 	 	if( send( client_sock , buf , strlen(buf) , 0 ) < 0 ){ 		fprintf( stderr ," send failed . reason: %s\n", strerror(errno)); 		return -1; 	} 	return 0; } 	 void cat(int client_sock , FILE *fp){ 	char buf[1024] = { 0 }; 	 	// 1 .没次读取一个字符 	/* 	while( fread(buf , 1 , sizeof(buf), fp) >0 ){ 		int len = write( client_sock , buf , strlen(buf)); 		 		memset( buf , 0 ,sizeof(buf)); 	}*/ 	 	fseek(fp, 0, SEEK_END);     long size = ftell(fp);     fseek(fp, 0, SEEK_SET);      // 为文件分配缓冲区     char* buffer =  (char*)malloc(size);      // 读取文件数据     size_t bytesRead = fread(buffer, 1, size, fp);     if (bytesRead != size) {         printf("读取文件时发生错误\n");        return ;     } 	     // 使用文件数据进行操作...      printf("读取 %lu 字节的数据\n", bytesRead); 	 int len = write( client_sock , buffer , size); 	 if( len < 0){ 		 fprintf(stderr , "write failed . reason :%s\n", strerror(errno)); 	 }         free(buffer); 	 	// 2. 没次发 	 	//-- 无图片的版本 	/*fgets( buf ,sizeof(buf) , fp); 	while( !feof(fp)){ 		int len = write( client_sock , buf , strlen(buf)); 		if(len < 0){ 			fprintf(stderr , "write failed . reason :%s\n", strerror(errno)); 			break; 		} 		fprintf(stdout , "%s", buf); 		fgets( buf ,sizeof(buf) , fp); 	}*/ }  void do_http_response1( int client_sock){ 	//main_header   ->  状态行 + 消息报头     //响应代号 200 服务器存在请求资源,可以响应给客户端 	const char *main_header = "\ HTTP/1.1 200 OK\r\n\ Server:wServer\r\n\ Content-Type:text/html\r\n\ Connection:Close\r\n"; 	//回响正文 	const char* welcome_content="\ \n\ \n\ \n\ Tihis is a test\n\ \n\ \n\ \n\ 


\n\

早上好



\n\
\n\ 尊姓大名:\n\
芳龄几何:\n\


\n\ \n\
\n\
\n\ \n\ "; if( Debug ) fprintf(stdout , ".....do http_response.....\n"); // 1 .发送main_header int len = write( client_sock , main_header ,strlen(main_header)); if(Debug) fprintf(stdout , "main_header[%d] : %s\n", len ,main_header); // 2 .生成 Conten-Lenght(要发送的文件大小) ,并发送 int wc_len = strlen( welcome_content ); char sent_buf[64]={0}; len = snprintf( sent_buf , 64 ,"Content-Length:%d\r\n\r\n" , wc_len ); len = write(client_sock , sent_buf , len ); if(Debug) fprintf(stdout , "sent_buf[%d] : %s" , len ,sent_buf ); // 3. 发送html文件 len = write( client_sock , welcome_content , wc_len); if( Debug ) fprintf(stdout, "write[%d] : %s" , len , welcome_content ); } int get_line(int sock , char *buf ,int size ){ //每次读取一个字符 int count = 0 ; //当前已经读取到的字符大小 char ch = '\0'; int len = 0 ; while( (count < size -1) && ch!='\n'){ len = read(sock , &ch ,1); if( len == 1 ){ //正常读取成功 //处理 '\r(回车) \n' if( ch=='\r') continue; else if(ch=='\n'){ //buf[count] = '\0'; //手动添加字符串结束符 break; } //处理一般的字符 buf[count++] = ch; }else if( len < 0 ){ //读取出错的情况 perror("read fialed\n"); count = -1; break; }else { //len = 0 的情况 客户端关闭了sock连接 fprintf(stderr , "client close\n"); count = -1 ; break; } } if( count >=0) buf[count]='\0'; //if(Debug) printf("line information %s\n", buf); return count; } void not_found( client_sock ){ //状态行 + 消息报头 const char *reply = "\ HTTP/1.1 404 NOT FOUND\r\n\ Server:wServer\r\n\ Content-Type:text/html\r\n\ Connection:Close\r\n"; //404 const char *sent_buf = "\ \n\ \n\ \n\ \n\ 404 页面未找到\n\ \n\ \n\ \n\
\n\

404 NOT FOUND

\n\
\n\

抱歉,您试图访问的页面不存在。可能是链接错误或页面已被移除。

\n\

您可以点击下面的链接返回首页或者进行搜索。

\n\
\n\
\n\ \n\ "; int len = write( client_sock , reply ,strlen(reply)); if( Debug ) fprintf(stdout , "reply[%d] : %s",len , reply); // 发送 Conten-Lenght int sent_buf_size = strlen( sent_buf); char content_lenght[64] ={0}; len = snprintf( content_lenght , 64 ,"Content-Length:%d\r\n\r\n", sent_buf_size ); len = write( client_sock , content_lenght , len ); if( Debug ) fprintf(stdout , "content_lenght[%d]:%s", len , content_lenght); // 3. 发送响应正文 len = write( client_sock , sent_buf , sent_buf_size ); if(Debug) fprintf(stdout ,"%s", sent_buf); } void unimplemented(int client_sock ){ //状态行 + 消息报头 const char *reply = "\ HTTP/1.1 501 Method Not Implemented\r\n\ Server:wServer\r\n\ Content-Type:text/html\r\n\ Connection:Close\r\n"; //501 const char *sent_buf = "\ \n\ \n\ \n\ \n\ HTTP 状态 501 – Method Not Implemented\n\ \n\ \n\ \n\

HTTP 状态 501 – Method Not Implemented

\n\
\n\

类型异常报告

\n\

消息 执行出异常

\n\

描述 客户端请求方法有异常

\n\
\n\

Linux

\n\ \n\ "; int len = write( client_sock , reply ,strlen(reply)); if( Debug ) fprintf(stdout , "reply[%d] : %s",len , reply); // 发送 Conten-Lenght int sent_buf_size = strlen( sent_buf); char content_lenght[64] ={0}; len = snprintf( content_lenght , 64 ,"Content-Length:%d\r\n\r\n", sent_buf_size ); len = write( client_sock , content_lenght , len ); if( Debug ) fprintf(stdout , "content_lenght[%d]:%s", len , content_lenght); // 3. 发送响应正文 len = write( client_sock , sent_buf , sent_buf_size ); if(Debug) fprintf(stdout ,"%s", sent_buf); } void bad_request( int client_sock ){ //状态行 + 消息报头 const char *reply = "\ HTTP/1.1 400 BAD REQUEST\r\n\ Server:wServer\r\n\ Content-Type:text/html\r\n\ Connection:Close\r\n"; //400 const char *sent_buf = "\ \n\ \n\ \n\ \n\ HTTP 状态 400 – Method Not Implemented\n\ \n\ \n\ \n\

HTTP 状态 400 – Method Not Implemented

\n\
\n\

类型异常报告

\n\

消息 执行出异常

\n\

描述 客户端请求格式异常

\n\
\n\

Linux

\n\ \n\ "; int len = write( client_sock , reply ,strlen(reply)); if( Debug ) fprintf(stdout , "reply[%d] : %s",len , reply); // 发送 Conten-Lenght int sent_buf_size = strlen( sent_buf); char content_lenght[64] ={0}; len = snprintf( content_lenght , 64 ,"Content-Length:%d\r\n\r\n", sent_buf_size ); len = write( client_sock , content_lenght , len ); if( Debug ) fprintf(stdout , "content_lenght[%d]:%s", len , content_lenght); // 3. 发送响应正文 len = write( client_sock , sent_buf , sent_buf_size ); if(Debug) fprintf(stdout ,"%s", sent_buf); } void Internal_Error(int client_sock){ //状态行 + 消息报头 const char *reply = "\ HTTP/1.1 500 Internal Server Error\r\n\ Server:wServer\r\n\ Content-Type:text/html\r\n\ Connection:Close\r\n"; //500 const char *sent_buf = "\ \n\ \n\ \n\ \n\ HTTP 状态 500 – 内部服务器错误\n\ \n\ \n\ \n\

HTTP 状态 500 – Internal Server Error

\n\
\n\

类型异常报告

\n\

消息 执行出异常

\n\

描述 服务器收到请求, 因为自身原因没发响应。

\n\
\n\

Linux

\n\ \n\ "; int len = write( client_sock , reply ,strlen(reply)); if( Debug ) fprintf(stdout , "reply[%d] : %s",len , reply); // 发送 Conten-Lenght int sent_buf_size = strlen( sent_buf); char content_lenght[64] ={0}; len = snprintf( content_lenght , 64 ,"Content-Length:%d\r\n\r\n", sent_buf_size ); len = write( client_sock , content_lenght , len ); if( Debug ) fprintf(stdout , "content_lenght[%d]:%s", len , content_lenght); // 3. 发送响应正文 len = write( client_sock , sent_buf , sent_buf_size ); if(Debug) fprintf(stdout ,"%s", sent_buf); }

总结:

代码资源 + 数据 

链接:https://pan.baidu.com/s/1Mrq7EAeVYFkxXrK68yp9vA?pwd=0307 
提取码:0307 

相关内容

热门资讯

Apache HTTP ser... 解压移动至C盘管理员身份运行CMD,进入bin目录,执行httpd -k...
可以与宝塔共存的一个 “魔法”... 前言之前有一期我们搭建了一个服务器监控,颜值非常不错,这期我们再来搭建一...
Cookie是一种在网站服务器... Cookie是一种在网站服务器和浏览器之间传输的小型数据片段。当用户访问一个网站时,服...
将本地Django项目部署到服... 最近因为项目的需求开始正在搭建一个个人网站。在本地完成了项目后端的内容后需要部署到服务器上以供用户访...
【在服务器CentOS7系统上... 在服务器CentOS7系统上使用Docker安装Ubuntu20.04 X86使用交叉编译链6.3版...
北斗、网络时钟服务器(NTP授... 北斗、网络时钟服务器(NTP授时服务器)几种设置方法计算机网络必须设立属...
C#WPF实现TCP服务器客户... 一、TCP服务器1、三个重要对象:Tcp监听、客户端、数据网络流 2、设置监听...
【Liunx常用操作】配置sf... 提示:为保证文章的正确性和实用性,文章内容可能会不定时优化改进ÿ...
logback服务器日志删除原...     查看以下的logback官方文档Chapter 4: Appendershttps://lo...
使用SSH远程连接Ubuntu... 1、基础知识      VirtualBox 是一款开源虚拟机软件,使用者可以在Vir...