简单的网络服务器不起作用

我正在尝试在C中编写一个Web服务器。我知道我可以使用许多不同的库,但我希望它只能用winsock运行。 服务器和客户端可以来回发送数据,但加载网页是不可能的。 每次我收到“服务器无法访问”消息,但在服务器上我收到正在发送正文的消息。 我究竟做错了什么?

编辑我正在使用chrome和microsoft edge

#include  #include  #include #pragma comment(lib,"ws2_32.lib") void error(const char* err){ printf("ERROR: %s\n", err); exit(1); } char* readline(SOCKET s){ FILE * f = tmpfile(); char rec; int i=0; while(recv(s, &rec, 1, 0)>0){ i++; if(rec!='\r' && rec!='\n') fwrite(&rec, 1, 1, f); if(rec=='\r' || rec=='\n') break; } if(i==0){ fclose(f); return NULL; } fseek(f, 0, SEEK_END); long long size = ftell(f); fseek(f, 0, SEEK_SET); char * d = (char*) malloc(size); memset (d,0,size); fread(d, 1, size, f); fclose(f); return d; } void flush(SOCKET s){ while(recv(s, NULL, 1, 0)>0){ } } void main(){ // CREATE SERVER WSADATA wsa; if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) error("WSAStartup"); SOCKET s; if((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) error("socket"); struct sockaddr_in server; server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(80); if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) error("bind"); // SERVER CREATED while(1){ listen(s, 1); int c = sizeof(struct sockaddr_in); SOCKET csock; struct sockaddr_in client; if((csock = accept(s, (struct sockaddr*)&client, &c))==INVALID_SOCKET) continue; char *client_ip = inet_ntoa(client.sin_addr); printf("Incomming connection: %s\n", client_ip); char * head = readline(csock); if(strncmp(head, "GET", 3)==0){ flush(csock); char response[] = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n\r\n" "test" "Test123"; send(csock, response, strlen(response), 0); printf("%s\n", "HTML body sended"); }else if(strncmp(head, "HEAD", 4)==0){ flush(csock); char response[] = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n\r\n"; send(csock, response, strlen(response), 0); printf("%s\n", "HTML head sended"); } closesocket(csock); } closesocket(s); WSACleanup(); } 

这个function:

 void flush(SOCKET s){ while(recv(s, NULL, 1, 0)>0){ } } 

在客户端(浏览器)重置连接之前,不会读取缓冲区中的所有内容。 如果检查send(csock, response, strlen(response), 0);返回的值send(csock, response, strlen(response), 0); 你会看到一个SOCKET_ERROR 。 调用WSAGetLastError()将返回

代码0x2745 =已建立的连接已被主机中的软件中止。

你用来读取socket的方式真是太丑了! 使用带有FIONREAD ioctlsocket()来获取要读取的字符数:

 char* readline(SOCKET s) { size_t MsgLen = 0; char *Msg = NULL; unsigned long Len; int res; while (0 == (res=ioctlsocket(s, FIONREAD, &Len))) { if (SOCKET_ERROR == Len) { if (Msg) { free(Msg); Msg = NULL; } return NULL; } if (!Len && MsgLen) break; if (!Msg) Msg = malloc(Len); else Msg = realloc(Msg, MsgLen + Len); recv(s, Msg+MsgLen, Len, 0); MsgLen += Len; } return Msg; } 

要使用它修复你的来源:

 char response[] = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n\r\n" "test" "Test123\r\n"; char response[] = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n\r\n"; int main(int argc, char *argv[]) { // CREATE SERVER WSADATA wsa; if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) error("WSAStartup"); SOCKET s; if((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) error("socket"); struct sockaddr_in server; server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons(80); if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR) error("bind"); // SERVER CREATED while(1){ listen(s, 1); int c = sizeof(struct sockaddr_in); SOCKET csock; struct sockaddr_in client; if((csock = accept(s, (struct sockaddr*)&client, &c))==INVALID_SOCKET) continue; char *client_ip = inet_ntoa(client.sin_addr); printf("Incoming connection: %s\n", client_ip); char * head = NULL; do { head = readline(csock); } while (!head); if(strncmp(head, "GET", 3)==0) { if (SOCKET_ERROR == send(csock, response, strlen(response), 0)) { WSAGetLastError(); } printf("%s\n", "HTML body sended"); } else if(strncmp(head, "HEAD", 4)==0) { send(csock, response, strlen(response), 0); printf("%s\n", "HTML head sended"); } closesocket(csock); } closesocket(s); WSACleanup(); }