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.hqwc.cn/news/279319.html

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

相关文章

我 爱 你

我爱你 可是我不敢说 我怕我说了 你会离我而去 我不怕你离去 可是我怕你离开了我 再没有人像我这样爱你 现代人说&#xff1a;初中生的爱情是一起回家&#xff0c;高中生的爱情是一起吃饭&#xff0c;大学生的爱情是一起睡觉&#xff0c;结婚了的爱情是一起回家吃饭然后…

LT7911D是TYPE-C/DP或者EDP转2 PORT MIPI和LVDS加音频

1.概述&#xff1a; T7911D是一款高性能TYPE-C/DP/EDP转2 PORT MIPI或者LVDS的芯片&#xff0c;目前主要在AR/VR或者显示器上应用的很多&#xff0c;对于DP1.2输入&#xff0c;LT7911D可配置为1/2/4车道。自适应均衡化使其适用于长电缆应用&#xff0c;最大带宽可达21.6Gbps。…

FGSM、PGD、BIM对抗攻击算法实现

本篇文章是博主在AI、无人机、强化学习等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在AI学…

win10电脑字体大小怎么设置?介绍四种方法

在Win10操作系统中&#xff0c;字体大小的设置对于用户来说是一个非常重要的问题。合适的字体大小能够保护我们的视力&#xff0c;提高我们的工作效率。本文将介绍几种常用的方法来调整Win10电脑的字体大小&#xff0c;帮助用户轻松设置自己喜欢的字体大小。 方法一&#xff1…

【C++11特性篇】C++11中新增的initializer_list——初始化的小利器(2)

前言 大家好吖&#xff0c;欢迎来到 YY 滴C11系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 目录 一.探究std::initializer_list是什么…

让高清媒体无限畅享——Movist Pro for Mac推广文章

随着科技的迅猛发展&#xff0c;高清媒体已经成为我们日常生活中不可或缺的一部分。无论是观看电影、追剧、还是欣赏高清音乐视频&#xff0c;我们都希望能够获得最佳的视听体验。为了满足这一需求&#xff0c;我们向大家推荐一款强大的高清媒体播放器——Movist Pro for Mac。…

Redis新数据类型-Bitmaps

目录 Bitmaps 简介 命令 1. setbit (1) 格式 (2) 实例 2. getbit (1) 格式 (2) 实例 3. bitcount (1) 格式 (2) 实例 4. bitop (1) 格式 (2) 实例 我的其他博客 Bitmaps 简介 Bitmaps 是 Redis 的一种新数据类型&#xff0c;它是一种用于存储位信息的数据结构&…

进程优化软件(Process Lasso pro) v10.2.0.7-好用的系统优化软件-能够为用户提供超多专业的算法

调试进程级别的系统优化工具&#xff0c;主要功能是基于其特别的算法动态调整各个进程的优先级并设为合理的优先级以实现为系统减负的目的&#xff0c;可有效避免蓝屏、假死、进程停止响应、进程占用 CPU 时间过多等症状。同时它还具备前台进程推进、工作集修整、进程黑名单等附…

移动端机器学习框架 MDL 简介与实践

Mobile-deep-learning&#xff08;MDL&#xff09; MDL 是百度研发的可以部署在移动端的基于卷积神经网络实现的移动端框架&#xff0c;可以应用在图像识别领域。 具体应用&#xff1a;在手机百度 App 中&#xff0c;用户只需要点击自动拍开关&#xff0c;将手机对准物体&…

计算机组成原理-选择语句和循环语句的汇编表示

文章目录 选择语句jmpjxx示例&#xff1a;选择语句的机器级表示扩展&#xff1a;cmp指令的底层原理 循环语句使用条件转移指令实现循环用loop指令实现循环 选择语句 不一定知道指令的位置&#xff0c;所以jmp直接跳转到指令的位置很难办 jmp 标号相当于位置&#xff0c;名字…

点燃温暖时光:探索酒精壁炉的独特历史与现代化魅力

酒精壁炉的历史可以追溯到18世纪末。最初&#xff0c;人们用酒精在暖炉或炉子中燃烧&#xff0c;以获得热量。19世纪初&#xff0c;法国发明家提出了利用酒精燃烧来供暖的概念。这一概念被逐渐应用于家庭取暖装置&#xff0c;酒精壁炉也开始在欧洲兴起。 随着科技的发展&#x…

MQTT 介绍与学习 —— 筑梦之路

之前写过的相关文章&#xff1a; MQTT协议&#xff08;转载&#xff09;——筑梦之路_mqtt url-CSDN博客 k8s 部署mqtt —— 筑梦之路-CSDN博客 CentOS 7 搭建mqtt服务——筑梦之路_腾讯云宝塔搭 centos 7.9.2009 x86_64 建标准mqtt服务器-CSDN博客 mqtt简介 MQTT&#xff…