本文介绍了简单的网络服务器无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试用C语言编写一个网络服务器.我知道我可以为此使用许多不同的库,但是我希望它只能与winsock一起运行.服务器和客户端可以来回发送数据,但是无法加载网页.每次我收到服务器无法访问"消息,但在服务器上却收到消息,指出正文已发送.我在做什么错了?

I'm trying to write a webserver in C. I know I could use many different libraries for that, but I want it to run only with winsock. The server and a client can send data back and forth but loading the webpage is impossible. Every time I get a 'server unreachable' message, but on the server I get the message that the body was sent. What am I doing wrong?

edit 我正在使用Chrome和Microsoft Edge

edit I'm using chrome and 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();
}

推荐答案

此功能:

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

不读取任何内容,直到客户端(浏览器)重置连接后才将所有内容放入缓冲区.如果检查send(csock, response, strlen(response), 0);返回的值,则会看到SOCKET_ERROR.呼叫WSAGetLastError()将返回

reads nothing letting all in the buffer until the client (the browser) reset the connection.If you check the value returned by send(csock, response, strlen(response), 0); you'll see a SOCKET_ERROR. Calling WSAGetLastError() will return

您用来读取套接字的方式确实很丑陋!将ioctlsocket()FIONREAD结合使用以获得要读取的字符数:

The way you use to read socket is really ugly! Use ioctlsocket() with FIONREAD to obtain the number of chars to read:

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

要使用它来修复您的来源:

To use it fix your source:

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

这篇关于简单的网络服务器无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 19:20