C语言写的 mini版的 http 服务器 , 很详细

文章目录

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

效果展示

例如: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 FOUNDfprintf( 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 Implementedfprintf(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 Implementedunimplemented(client_sock);}	}else {   //客户端发送的请求格式有问题 相应 400  BAD REQUESTbad_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 bodyif( !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 ErrorInternal_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<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<ctype.h>
#include<arpa/inet.h>
#include<errno.h>
#include<sys/stat.h>
#include<pthread.h>#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; //选择协议族IPV4server_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 FOUNDfprintf( 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 Implementedfprintf(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 Implementedunimplemented(client_sock);}	}else {   //客户端发送的请求格式有问题 相应 400  BAD REQUESTbad_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 bodyif( !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 ErrorInternal_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="\
<html lang = \"zh-CN\">\n\
<head>\n\
<meta content = \"text/html;charset=utf-8\"http-equiv=\"Content-Type\">\n\
<title>Tihis is a test</title>\n\
</head>\n\
<body>\n\
<dir align = center height =\"500px\">\n\
<br/><br/><br/>\n\
<h2>早上好</h2><br/><br/>\n\
<form action = \"commit\"method = \"post\">\n\
尊姓大名:<input type =\"text\" name=\"name\"/>\n\
<br/> 芳龄几何:<input type =\"password\" name =\"age\"/>\n\
<br/><br/><br/><input type =\"submit\" value=\"提交\"/>\n\
<input type =\"reset\" value =\"重置\"/>\n\
</form>\n\
</dir>\n\
</body>\n\
</html>";if( Debug ) fprintf(stdout , ".....do http_response.....\n");// 1 .发送main_headerint 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";//404const char *sent_buf = "\
<!DOCTYPE html>\n\
<html lang=\"zh-CN\">\n\
<head>\n\
<meta charset=\"UTF-8\">\n\
<title>404 页面未找到</title>\n\
<style>\n\
body {\n\
text-align: center;\n\
padding: 150px;\n\
font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n\
}\n\
h1 {\n\
font-size: 50px;\n\
}\n\
body {\n\
font-size: 20px;\n\
}\n\
article {\n\
display: block;\n\
text-align: left;\n\
width: 650px;\n\
margin: 0 auto;\n\
}\n\
a {\n\
color: #00a2e8;\n\
text-decoration: none;\n\
}\n\
a:hover {\n\
text-decoration: underline;\n\
}\n\
</style>\n\
</head>\n\
<body>\n\
<article>\n\
<h1>404 NOT FOUND</h1>\n\
<div>\n\
<p>抱歉,您试图访问的页面不存在。可能是链接错误或页面已被移除。</p>\n\
<p>您可以点击下面的链接返回<a href=\"/\">首页</a>或者进行搜索。</p>\n\
</div>\n\
</article>\n\
</body>\n\
</html>";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";//501const char *sent_buf = "\
<!DOCTYPE html>\n\
<html>\n\
<head>\n\
<meta charset=\"utf-8\">\n\
<title>HTTP 状态 501 – Method Not Implemented</title>\n\
<style type=\"text/css\">\n\
h1{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: white;\n\
background-color: #525d76;\n\
font-size: 30px;\n\
}\n\
body{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: black;\n\
background-color: white;\n\
}\n\
b{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: white;\n\
background-color: #525d76;\n\
}\n\
p{\n\
font-family:Tahoma,Arial,scans-serif;\n\
background: white;\n\
color: black;\n\
}\n\
h3{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: white;\n\
background-color: #525d76;\n\
}\n\
</style>\n\
</head>\n\
<body>\n\
<h1 >HTTP 状态 501 – Method Not Implemented</h1>\n\
<hr class=\"line\">\n\
<p ><b >类型</b>异常报告</p>\n\
<p ><b>消息</b> 执行出异常</p>\n\
<p ><b>描述</b>  客户端请求方法有异常</p>\n\
<hr class=\"line\">\n\
<h3> Linux</h3>\n\
</body>\n\
</html>";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";//400const char *sent_buf = "\
<!DOCTYPE html>\n\
<html>\n\
<head>\n\
<meta charset=\"utf-8\">\n\
<title>HTTP 状态 400 – Method Not Implemented</title>\n\
<style type=\"text/css\">\n\
h1{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: white;\n\
background-color: #525d76;\n\
font-size: 30px;\n\
}\n\
body{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: black;\n\
background-color: white;\n\
}\n\
b{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: white;\n\
background-color: #525d76;\n\
}\n\
p{\n\
font-family:Tahoma,Arial,scans-serif;\n\
background: white;\n\
color: black;\n\
}\n\
h3{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: white;\n\
background-color: #525d76;\n\
}\n\
</style>\n\
</head>\n\
<body>\n\
<h1 >HTTP 状态 400 – Method Not Implemented</h1>\n\
<hr class=\"line\">\n\
<p ><b >类型</b>异常报告</p>\n\
<p ><b>消息</b> 执行出异常</p>\n\
<p ><b>描述</b>  客户端请求格式异常</p>\n\
<hr class=\"line\">\n\
<h3> Linux</h3>\n\
</body>\n\
</html>";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";//500const char *sent_buf = "\
<!DOCTYPE html>\n\
<html>\n\
<head>\n\
<meta charset=\"utf-8\" />\n\
<title>HTTP 状态 500 – 内部服务器错误</title>\n\
<style type=\"text/css\">\n\
h1{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: white;\n\
background-color: #525d76;\n\
font-size: 30px;\n\
}\n\
body{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: black;\n\
background-color: white;\n\
}\n\
b{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: white;\n\
background-color: #525d76;\n\
}\n\
p{\n\
font-family:Tahoma,Arial,scans-serif;\n\
background: white;\n\
color: black;\n\
}\n\
h3{\n\
font-family: Tahoma,Arial,scans-serif;\n\
color: white;\n\
background-color: #525d76;\n\
}\n\
</style>\n\
</head>\n\
<body>\n\
<h1 >HTTP 状态 500 – Internal Server Error</h1>\n\
<hr class=\"line\">\n\
<p ><b >类型</b>异常报告</p>\n\
<p ><b>消息</b> 执行出异常</p>\n\
<p ><b>描述</b> 服务器收到请求, 因为自身原因没发响应。</p>\n\
<hr class=\"line\">\n\
<h3> Linux</h3>\n\
</body>\n\
</html>";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 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/226049.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无心剑英译朱自清《匆匆》

匆匆 Vanished in Haste 朱自清 By Zhu Ziqing 燕子去了,有再来的时候;杨柳枯了,有再青的时候;桃花谢了,有再开的时候。但是,聪明的,你告诉我,我们的日子为什么一去不复返呢?——是有人偷了他们罢:那是谁?又藏在何处呢?是他们自己逃走了罢:现在又到了哪里呢? Sw…

如何使用Docker进行容器的备份和恢复

一 简介&#xff1a; 在使用Docker进行应用程序的容器化部署时&#xff0c;我们经常需要对容器进行备份和恢复操作。备份容器可以保证数据的安全性&#xff0c;而恢复操作可以帮助我们快速恢复出现问题的容器。本文将介绍如何使用Docker进行容器的备份和恢复&#xff0c;同时提…

Buck电源设计常见的一些问题(二)MOS管炸机问题

MOS管炸机问题 1.概述2.MOS管的相关参数3.过电压失效4.过电流失效5.静电放电和热失效1.概述 在我们做电源产品或者电机控制器时候,经常会坏MOS管。我相信90%以上的硬件工程师在职场生涯中都会遇到这类问题。然而这类问题也总是让人防不胜防。经常我们都会开玩笑的说,没烧过管…

【数据结构第 6 章 ④】- 用 C 语言实现图的深度优先搜索遍历和广度优先搜索遍历

目录 一、深度优先搜索 1.1 - 深度优先搜索遍历的过程 1.2 - 深度优先搜索遍历的算法实现 二、广度优先搜索 2.1 - 广度优先搜索遍历的过程 2.2 - 广度优先搜索遍历的算法实现 和树的遍历类似&#xff0c;图的遍历也是从图中某一顶点出发&#xff0c;按照某种方法对图中所…

壹基金瑞金东升社区儿童服务站上演“甜蜜冬日”亲子DIY蛋糕秀

12月9日上午&#xff0c;一场温情满溢的亲子DIY蛋糕活动&#xff0c;在壹基金瑞金东升社区儿童服务站拉开了帷幕&#xff0c;空气里有香甜的奶油味道&#xff0c;浓浓的温馨气息感染着在场的每一个人。 自己动手做的&#xff0c;才有意义&#xff0c;蛋糕DIY是一项很好的亲子活…

想做游戏开发,我应该会点啥?

在知乎上&#xff0c;经常能看到类似“如何入门游戏开发”这样的问题&#xff0c;这篇文章&#xff0c;我试着概括性的对游戏开发所需要的技能做一个总结&#xff0c;希望大家对游戏开发能有一个基本的认识~ 游戏开发基础要求高么&#xff1f; 和其他程序猿一样&#xff0c;要…

前后端交互—开发一个完整的服务器

代码下载 初始化 新建 apiServer 文件夹作为项目根目录&#xff0c;并在项目根目录中运行如下的命令&#xff0c;初始化包管理配置文件: npm init -y运行如下的命令&#xff0c;安装 express、cors: npm i express cors在项目根目录中新建 app.js 作为整个项目的入口文件&a…

12V升18V4A同步升压恒压WT3210

12V升18V4A同步升压恒压WT3210 WT3210 是一款高功率密度的全集成同步升压转换器&#xff0c;内部集成的功率MOSFET管导通电阻为上管8mΩ和下管15mΩ。可为便携式系统提供空间小尺寸 解决方案。WT3210具有 2.7V 至 20V 的宽输入电压范围&#xff0c;应用在单节或两节锂电池的便携…

关于嵌入式开发的一些信息汇总:嵌入式C开发人员、嵌入式系统Linux

关于嵌入式开发的一些信息汇总&#xff1a;嵌入式C开发人员、嵌入式系统Linux 1 关于嵌入式 C 开发人员1.1 嵌入式 C 开发人员必须具备的一些基本技能是&#xff1a;1.2 嵌入式C开发的应用案例 2 如何学习用于嵌入式系统的 Linux2.1 如何学习Linux2.1.1 第一步&#xff1a;创建…

漏刻有时百度地图API实战开发(12)(切片工具的使用、添加自定义图层TileLayer)

TileLayer向地图中添加自定义图层 var tileLayer new BMap.TileLayer();tileLayer.getTilesUrl function (tileCoord, zoom) {var x tileCoord.x;var y tileCoord.y;return images/tiles/ zoom /tile- x _ y .png;}var lockMap new BMap.MapType(lock_map, tileLaye…

【MySQL】MySQL 在 Centos 7环境安装教程

文章目录 1.卸载不要的环境2.检查系统安装包3.获取mysql官方yum源4.安装mysql yum 源&#xff0c;对比前后yum源5.安装mysql服务6.查看配置文件和数据存储位置7.启动服务和查看启动服务8.登录9.配置my.cnf 1.卸载不要的环境 先检查是否有mariadb存在 ps ajx |grep mariadb如果…

C语言定长数组 变长数组 柔性数组

C语言定长数组 变长数组 柔性数组 文章目录 C语言定长数组 变长数组 柔性数组1. 定长数组2. 变长数组3. 柔性数组3.1 结构体的大小3.2 柔性数组的使用 1. 定长数组 在C99标准之前&#xff0c;C语言在创建数组的时候&#xff0c;数组的大小只能使用常量&#xff0c;常量表达式来…

【EI会议征稿】第三届电子信息工程、大数据与计算机技术国际学术会议(EIBDCT 2024)

第三届电子信息工程、大数据与计算机技术国际学术会议&#xff08;EIBDCT 2024&#xff09; 2024 3rd International Conference on Electronic Information Engineering, Big Data and Computer Technology 第三届电子信息工程、大数据与计算机技术国际学术会议&#xff08;…

小狐狸GPT付费2.4.9弹窗版学习源码介绍

小狐狸GPT付费2.4.9弹窗版学习源码是一套基于GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型的开源代码库&#xff0c;旨在帮助开发者快速构建和训练自己的语言模型。该源码集成了多个先进的自然语言处理技术&#xff0c;包括预训练、微调、对话生成等&am…

云服务领取证书,注册域名,实现nginx服务配置证书

目录 1.登录网址腾讯云 2.腾讯云注册域名 3.实名认证&#xff0c;上传信息 4.域名注册 5.领取证书 6.域名与证书绑定 7.下载证书 8.设置环境 9.域名解析 10. 本地域名解析 11.上传证书到目录 12.nginx配置文件做地址重写到证书域名 13.配置证书conf 14.设置index…

磁盘坏道修复工具-是一款非常方便实用的磁盘坏道修复软件-供大家学习研究参考

1、支持磁盘数据擦除。 2、杜绝因硬盘坏道&#xff0c;而产生个人隐私数据泄露的问题。 3、支持对该磁盘格式化。 下载&#xff1a;https://download.csdn.net/download/weixin_43097956/88625682

关于“Python”的核心知识点整理大全22

目录 ​编辑 9.4.2 在一个模块中存储多个类 虽然同一个模块中的类之间应存在某种相关性&#xff0c;但可根据需要在一个模块中存储任意数量的 类。类Battery和ElectricCar都可帮助模拟汽车&#xff0c;因此下面将它们都加入模块car.py中&#xff1a; car.py my_electric_car…

基于 Gin 的 HTTP 代理上网行为记录 demo

前言: 前端时间写了好几篇使用 Gin 框架来做 HTTP 代理 demo 的文章&#xff0c;然后就想着做一个记录上网行为的小工具&#xff0c;就是简单记录看看平时访问了什么网站&#xff08;基于隧道代理的&#xff0c;不是中间人代理&#xff0c;所以只能记录去了哪里&#xff0c;不能…

wps左上角有绿色小三角的数字如何求和

1.这个状态是求和不了的&#xff0c;使用求和公式求出来的也是0 2.进行如下操作 3.转换好后 则可以求和成功了

深度学习 Day16——P5运动鞋识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 文章目录 前言1 我的环境2 代码实现与执行结果2.1 前期准备2.1.1 引入库2.1.2 设置GPU&#xff08;如果设备上支持GPU就使用GPU,否则使用C…