改了一个简单的http服务器遇到一个问题
浏览器请求并成功返回html文件,但是HTML页面中需要加载一些js css文件等,抓包显示服务器能接收到相应的请求并返回了相应的js css文件,但是浏览器报错如图
.C文件
#include
#include #include #include #include #include #include #include #include #include #include #include #include #include #include "httpsever.h" #define SERVER_PORT 8800 #define ON_DEBUG const char month_tab[48] = "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec "; const char day_tab[] = "Sun,Mon,Tue,Wed,Thu,Fri,Sat,"; time_t current_time; static int debug = 1; void* do_http_request(void *client_sock); //http处理线程函数 int get_line(int sock, char *buf, int size); int Parse_Request(struct Request *request); void Process_Request(struct Request *request); void GET_Process(struct Request *request); void POST_Process(struct Request *request); int Get_FILE(struct Request *request); int do_http_Response(struct Request *request); int Headers(struct Request *request); void Send_Body(struct Request *request); void rfc822_time_buf(char *buf, time_t s); void not_found(int client_sock);//404 void unimplemented(int client_sock);//500 void bad_request(int client_sock); //400 void inner_error(int client_sock); int main(void){ int sock; struct sockaddr_in server_addr; //创建socket sock = socket(AF_INET, SOCK_STREAM, 0); int opt =1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); //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);//绑定端口号80 //绑定socket bind(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)); //监听socket listen(sock, 128); time(¤t_time); int done =1; while(done){ struct sockaddr_in client; int client_sock, len, i; char client_ip[64]; char buf[256]; pthread_t id; int* pclient_sock = NULL; socklen_t client_addr_len; client_addr_len = sizeof(client); #ifdef ON_DEBUG printf("\n等待客户端的连接\n"); #endif client_sock = accept(sock, (struct sockaddr *)&client, &client_addr_len); //打印客服端IP地址和端口号 printf("\nclient ip: %s\t port : %d\n", inet_ntop(AF_INET, &client.sin_addr.s_addr,client_ip,sizeof(client_ip)), ntohs(client.sin_port)); /*处理http 请求,读取客户端发送的数据*/ // do_http_request(client_sock); // do{ // len = get_line(client_sock, buf, sizeof(buf)); // if(debug) printf("heard: %s\n", buf); // }while(len>0); //启动线程处理http 请求 pclient_sock = (int *)malloc(sizeof(int)); *pclient_sock = client_sock; pthread_create(&id, NULL, do_http_request, (void *)pclient_sock); // close(client_sock); } close(sock); return 0; } /*************************************************** *请求处理线程 :do_http_request(void* pclient_sock); *pclient_sock : 客户端socket ****************************************************/ void* do_http_request(void* pclient_sock){ int len = 0; char buf[256]; struct timeval timeout; struct Request request,*ptrrequest; // memset(&request,0,sizeof(request)); timeout.tv_sec = READ_TIMEOUT ; timeout.tv_usec = 0 ; /*初始化请求结构体默认参数*/ ptrrequest = &request; request.client_sock = *(int *)pclient_sock; request.readTumeout = &timeout; request.status = 0 ; /* see #defines.h */ request.keepalive = 0; /* keepalive status 1 keepalive , 0 closelive */ request.fp = NULL ; /*descriptor of requested file*/ request.data =NULL ; request.send_buf = NULL; /*设置等待超时*/ if (setsockopt(request.client_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1) { printf("setsockopt failed:"); } do{ request.Request_Length = 0 ; /*Content-Length*/ request.send_buf_len = 0 ; memset(request.path,0,256); /* pathname of requested file */ int ret = Parse_Request(ptrrequest); /*解析客户端http请求*/ if(ret == 0) { Process_Request(ptrrequest); /*处理客户端http请求*/ } if(request.data) {free(request.data); request.data = NULL;} if(request.send_buf) {free(request.send_buf); request.send_buf = NULL;} }while(request.keepalive == 1); close(request.client_sock); if(pclient_sock) free(pclient_sock);//释放动态分配的内存 return NULL; } /*************************************************** *解析客户端请求 :do_http_request(int client_sock); *struct Request *request : 客户端请求结构体 ****************************************************/ int Parse_Request(struct Request *request) { int len = 0; char buf[256],tempbuf[256]; len = get_line(request->client_sock, buf, sizeof(buf)); #ifdef ON_DEBUG printf("请求第一行: %s\n", buf); #endif if(len > 0){//读到了请求行 /*获取请求方式GET or POST*/ int i=0, j=0; while(!isspace(buf[j]) && (i<sizeof(tempbuf)-1)){ tempbuf[i] = buf[j]; i++; j++; } tempbuf[i] = '\0'; // #ifdef ON_DEBUG // printf("request method: %s\n", tempbuf); // #endif if(strcmp("GET",tempbuf)==0) { request->method = GET; }else if(strcmp("POST",tempbuf)==0) { request->method = POST; // #ifdef ON_DEBUG // printf("method: %s\n", tempbuf); // #endif } while(isspace(buf[j])) { j++; };//跳过白空格 i = 0; /*读取path*/ while(!isspace(buf[j]) && (i<sizeof(request->path)-1)){ request->path[i] = buf[j]; i++; j++; } request->path[i] = '\0'; #ifdef ON_DEBUG printf("url: %s\n", request->path); #endif /*处理path中的?并将读取URL中的数据放到request->data堆空间*/ char *pos = strchr(request->path, '?'); if(pos){ *pos = '\0'; pos++; request->data = (char *)malloc(sizeof(pos)+1); memset(request->data,0,sizeof(pos)+1); strcpy(request->data,pos); memset(pos,0,sizeof(pos)); #ifdef ON_DEBUG printf("url data: %s\n", request->data); #endif } /*判断请求文件类型*/ if(strncmp("/js",request->path,3) ==0 ) { request->Content_Type = JS ; }else if(strncmp("/css",request->path,4) ==0 ) { request->Content_Type = CSS ; }else if(strncmp("/img",request->path,4) ==0 ) { request->Content_Type = PNG ; }else if(strncmp("/JPG",request->path,4) ==0 ) { request->Content_Type = JPG ; }else if(strncmp("/SET",request->path,4) ==0 ) { request->Content_Type = SET ; //设置请求 }else if(strncmp("/QUERY",request->path,6) ==0 ) { request->Content_Type = QUERY ; //查询请求 }else{ request->Content_Type = HTML ; } /*请求头部除第一行剩余数据处理,获取request->data*/ do{ memset(buf,0,sizeof(buf)); len = get_line(request->client_sock, buf, sizeof(buf)); #ifdef ON_DEBUG printf("%s\n", buf); #endif if(strncmp("Content-Length",buf,14) == 0) //读取Content-Length参数初始化数据堆空间 { request->Request_Length = atoi(&buf[16]); #ifdef ON_DEBUG printf("request->Length: %d\n", request->Request_Length); #endif if(request->Request_Length>0) request->data = (char *)malloc(request->Request_Length+1); memset(request->data,0,request->Request_Length+1); } else if(strncmp("Connection",buf,10) == 0) //读取Connection参数 { if(strncmp("keep-alive",&buf[12],10) == 0) { request->keepalive = 1; }else{ request->keepalive = 0; } } }while(len>0); /*读取请求数据实体*/ if(request->Request_Length>0) { len = read(request->client_sock, request->data, request->Request_Length); #ifdef ON_DEBUG printf("data: %s\n", request->data); #endif } }else{ request->keepalive = 0; return -1; } return 0; } /*************************************************** *请求处理 :Process_Request(struct Request *request); *struct Request *request : 客户端请求结构体 ****************************************************/ void Process_Request(struct Request *request) { switch(request->method) { case GET : //GET.... GET_Process(request); break; case POST : //POST.... POST_Process(request); break; } } //返回值: -1 表示读取出错, 等于0表示读到一个空行, 大于0 表示成功读取一行 int get_line(int sock, char *buf, int size){ int count = 0 ; char ch = '\0'; int len = 0; while( (count 1) && ch!='\n'){ len = read(sock, &ch, 1); if(len == 1){ if(ch == '\r'){ continue; }else if(ch == '\n'){ //buf[count] = '\0'; break; } //这里处理一般的字符 buf[count] = ch; count++; }else if( len == -1 ){//读取出错 perror("read failed"); count = -1; break; }else {// read 返回0,客户端关闭sock 连接. fprintf(stderr, "client close.\n"); count = -1; break; } } if(count >= 0) buf[count] = '\0'; return count; } void GET_Process(struct Request *request) { char temppath[256] = {0}; strcat(temppath,"./www"); if(strcmp("/",request->path) == 0) //GET请求空路劲时默认请求login.html { strcat(request->path,"login.html"); } if(request->Content_Type!=SET && request->Content_Type!=QUERY) {//请求文件 strcat(temppath,request->path); memcpy(request->path,temppath,strlen(temppath)); int ret = Get_FILE(request); if(ret == -1) return ; } do_http_Response(request); } int do_http_Response(struct Request *request) { if(request->Content_Type == SET || request->Content_Type == QUERY) { //进行设置或者查询任务并且返回,回复信息长度和回复信息 } int ret = Headers(request); if(!ret) { Send_Body(request); } if(request->fp!=NULL) { fclose(request->fp); request->fp = NULL; } } /**************************** *返回关于响应文件信息的http 头部 *输入: * client_sock - 客服端socket 句柄 * resource - 文件的句柄 *返回值: 成功返回0 ,失败返回-1 ******************************/ int Headers(struct Request *request){ struct stat st; int fileid = 0; char tmp[64]; char buf[1024]="HTTP/1.0 200 OK\r\nDate: " " " "\r\nServer: web Server\r\n"; rfc822_time_buf(buf + 23, 0); // strcpy(buf, "HTTP/1.0 200 OK\r\n"); // strcat(buf, "Server: web Server\r\n"); switch(request->Content_Type) { case JPG : strcat(buf, "Content-Type: image/jpeg\r\n"); break; case CSS : strcat(buf, "Content-Type: text/css\r\n"); break; case JS : strcat(buf, "Content-Type: text/javascript\r\n"); break; case PNG : strcat(buf, "Content-Type: image/png\r\n"); break; default : strcat(buf, "Content-Type: text/html\r\n"); break; } if(request->keepalive == 1) { strcat(buf, "Connection: Keep-Alive\r\n"); }else{ strcat(buf, "Connection: Close\r\n"); } snprintf(tmp, 64, "Keep-Alive: timeout=%ld\r\n", request->readTumeout->tv_sec); strcat(buf, tmp); memset(tmp,0,64); if(request->Content_Type == SET || request->Content_Type == QUERY) { snprintf(tmp, 64, "Content-Length: %d\r\n\r\n", request->send_buf_len); }else{ fileid = fileno(request->fp); if(fstat(fileid, &st)== -1){ inner_error(request->client_sock); return -1; } snprintf(tmp, 64, "Content-Length: %ld\r\n\r\n", st.st_size); } strcat(buf, tmp); #ifdef ON_DEBUG printf("Send Header:\n%s", buf); #endif if(send(request->client_sock, buf, strlen(buf), 0)<0){ fprintf(stderr, "send failed. data: %s, reason: %s\n", buf, strerror(errno)); return -1; } return 0; } /**************************** *说明:实现文件的内容按行读取并送给客户端 ****************************/ void Send_Body(struct Request *request){ char buf[1024]; int count = 1; if(request->Content_Type == SET || request->Content_Type == QUERY) { int len = write(request->client_sock, request->send_buf, request->send_buf_len); while(len<0 && count<3){//发送body 的过程中出现问题,重传 len = write(request->client_sock, request->send_buf, request->send_buf_len); count ++; } } else{ fgets(buf, sizeof(buf), request->fp); while(!feof(request->fp)){ int len = write(request->client_sock, buf, strlen(buf)); count = 1; while(len<0 && count<3){//发送body 的过程中出现问题,重试 fprintf(stderr, "send body error. reason: %s\n", strerror(errno)); len = write(request->client_sock, buf, strlen(buf)); count ++; } if(count == 3 && len<0 ) { break; } #ifdef ON_DEBUG fprintf(stdout, "%s", buf); #endif fgets(buf, sizeof(buf), request->fp); } } } void POST_Process(struct Request *request) { //若果请求路径为/(默认是HTML类型) } int Get_FILE(struct Request *request) { struct stat st; if(stat(request->path, &st)==-1){//文件不存在或是出错 not_found(request->client_sock); return -1; }else {//文件存在 // if(S_ISDIR(st.st_mode)){ //判断request->path是否是,目录是为真 // } request->fp = fopen(request->path, "r"); if(request->fp == NULL){ not_found(request->client_sock); return -1; } } } /* rfc822 (1123) time is exactly 29 characters long * "Sun, 06 Nov 1994 08:49:37 GMT" */ void rfc822_time_buf(char *buf, time_t s) { struct tm *t; char *p; unsigned int a; if (!s) { t = gmtime(¤t_time); } else t = gmtime(&s); p = buf + 28; /* p points to the last char in the buf */ p -= 3; /* p points to where the ' ' will go */ memcpy(p--, " GMT", 4); a = t->tm_sec; *p-- = '0' + a % 10; *p-- = '0' + a / 10; *p-- = ':'; a = t->tm_min; *p-- = '0' + a % 10; *p-- = '0' + a / 10; *p-- = ':'; a = t->tm_hour; *p-- = '0' + a % 10; *p-- = '0' + a / 10; *p-- = ' '; a = 1900 + t->tm_year; while (a) { *p-- = '0' + a % 10; a /= 10; } /* p points to an unused spot to where the space will go */ p -= 3; /* p points to where the first char of the month will go */ memcpy(p--, month_tab + 4 * (t->tm_mon), 4); *p-- = ' '; a = t->tm_mday; *p-- = '0' + a % 10; *p-- = '0' + a / 10; *p-- = ' '; p -= 3; memcpy(p, day_tab + t->tm_wday * 4, 4); } #if 1 void not_found(int client_sock){ const char * reply = "HTTP/1.0 404 NOT FOUND\r\n\ Content-Type: text/html\r\n\ \r\n\ \r\n\ \r\n\ \r\n\ NOT FOUND \r\n\ \r\n\ \r\n\文件不存在!\r\n\
The server could not fulfill your request because the resource specified is unavailable or nonexistent.\r\n\ \r\n\ "; int len = write(client_sock, reply, strlen(reply)); if(debug) fprintf(stdout, reply); if(len <=0){ fprintf(stderr, "send reply failed. reason: %s\n", strerror(errno)); } } void unimplemented(int client_sock){ const char * reply = "HTTP/1.0 501 Method Not Implemented\r\n\ Content-Type: text/html\r\n\ \r\n\ \r\n\ \r\n\
Method Not Implemented \r\n\ \r\n\ \r\n\HTTP request method not supported.\r\n\ \r\n\ "; int len = write(client_sock, reply, strlen(reply)); if(debug) fprintf(stdout, reply); if(len <=0){ fprintf(stderr, "send reply failed. reason: %s\n", strerror(errno)); } } void bad_request(int client_sock){ const char * reply = "HTTP/1.0 400 BAD REQUEST\r\n\ Content-Type: text/html\r\n\ \r\n\ \r\n\ \r\n\
BAD REQUEST \r\n\ \r\n\ \r\n\Your browser sent a bad request!\r\n\ \r\n\ "; int len = write(client_sock, reply, strlen(reply)); if(len<=0){ fprintf(stderr, "send reply failed. reason: %s\n", strerror(errno)); } } void inner_error(int client_sock){ const char * reply = "HTTP/1.0 500 Internal Sever Error\r\n\ Content-Type: text/html\r\n\ \r\n\ \r\n\ \r\n\ \r\n\
Inner Error \r\n\ \r\n\ \r\n\
服务器内部出错.\r\n\ \r\n\ "; int len = write(client_sock, reply, strlen(reply)); if(debug) fprintf(stdout, reply); if(len <=0){ fprintf(stderr, "send reply failed. reason: %s\n", strerror(errno)); } } #endif
#ifndef HTTPSEVER
#define HTTPSEVER
/*请求类型*/
#define GET 1
#define POST 2
/*请求文件类型*/
#define JPG 1
#define CSS 2
#define JS 3
#define HTML 4
#define PNG 5
#define SET 6 //设置请求/SET
#define QUERY 7 //查询请求/QUERY
#define READ_TIMEOUT 3 /*read超时时间*/
#include
#include
struct Request { /* pending requests */
int client_sock; /* client's socket fd */
int method; /* M_GET, M_POST, etc. */
int status; /* see #defines.h */
int keepalive; /* keepalive status 1 keepalive , 0 closelive */
int Request_Length; /*Content-Length*/
int send_buf_len;
int Content_Type; /*Type of requested file*/
char path[256]; /* pathname of requested file */
FILE * fp; /*descriptor of requested file*/
char *data;
char *send_buf;
struct timeval *readTumeout;
};
#endif
js css 加载问题的解决了,sendbody函数发送文件while逻辑有问题最后一行读出来没发送,现在png和jpg文件响应还是有问题
不知道你这个问题是否已经解决, 如果还没有解决的话:首先,根据问题描述,服务器能够成功接收js、css等文件的请求并返回相应的文件,说明问题出在浏览器无法正确显示页面上。考虑到js和css等文件的加载是异步进行的,可能会与页面的渲染顺序有关系。
其次,可以尝试在HTML页面中添加一些代码来检查加载js和css等文件的状态,例如检查是否成功加载、是否存在语法错误等。
示例代码:
<html>
<head>
<script type="text/javascript">
var cssLoaded = false;
var jsLoaded = false;
function checkCss() {
if (document.getElementById("myCss")) {
cssLoaded = true;
console.log("CSS loaded successfully.");
} else {
console.log("CSS not found.");
}
}
function checkJs() {
if (typeof(myJsVariable) !== 'undefined') {
jsLoaded = true;
console.log("JS loaded successfully.");
} else {
console.log("JS not found.");
}
}
setTimeout(checkCss, 1000);
setTimeout(checkJs, 1000);
</script>
</head>
<body>
<link id="myCss" rel="stylesheet" type="text/css" href="myStyle.css">
<script src="myScript.js"></script>
</body>
</html>
在这个例子中,我们添加了两个检查函数checkCss和checkJs,并通过setTimeout延迟一定时间后进行检查。在检查过程中,分别检查css和js是否成功被加载,如果成功则将相应的状态设为true,并输出相应信息。
需要注意的是,在checkJs中我们使用了myJsVariable变量进行检查,这是为了确保js文件中的内容能够被正确加载执行。我们需要在js文件中添加相应的代码:
var myJsVariable = true;
console.log("JS file loaded.");
这样做会输出"JS file loaded.",表示文件已被成功加载。
对于一些常见的错误,例如路径错误、文件名大小写问题等,可以利用开发者工具的Network面板来查看请求和返回的情况,并检查是否存在异常状态码、错误信息等。如果遇到其他问题,在问题描述中提供更具体的信息和详细的调试过程是非常有帮助的。
综上所述,我们需要考虑js和css等文件加载的顺序以及可能存在的错误,并通过增加代码来检查状态和调试问题。