socket example code c http server winsock

example - winsock client



El servidor web simple no funcionará (1)

Intento escribir un servidor web en C. Sé que podría usar muchas bibliotecas diferentes para eso, pero quiero que se ejecute solo con winsock. El servidor y un cliente pueden enviar datos hacia adelante y hacia atrás, pero cargar la página web es imposible. Cada vez que recibo un mensaje de "servidor inalcanzable", pero en el servidor aparece el mensaje de que se envió el cuerpo. ¿Qué estoy haciendo mal?

editar Estoy usando Chrome y Microsoft Edge

#include <stdio.h> #include <conio.h> #include<winsock2.h> #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" "<html><head><title>test</title>" "</head><body>Test123</body></html>"; 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(); }


Esta función:

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

no lee nada y deja todo en el búfer hasta que el cliente (el navegador) restablece la conexión. Si comprueba el valor devuelto por send(csock, response, strlen(response), 0); verá un SOCKET_ERROR . Llamando a WSAGetLastError() regresará

Código 0x2745 = Una conexión establecida fue cancelada por el software en su máquina host.

¡La forma en que la usas para leer el socket es realmente fea! Use ioctlsocket() con FIONREAD para obtener el número de caracteres para leer:

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; }

Para usarlo, arregla tu fuente:

char response[] = "HTTP/1.1 200 OK/r/n" "Content-Type: text/html/r/n/r/n" "<html><head><title>test</title>" "</head><body>Test123</body></html>/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(); }