多个连接webserver C.

时间:2017-11-06 10:36:30

标签: c sockets winapi webserver winsock

我需要用C编写一个非常基本的网络服务器。下面是我的代码。

问题在于我无法正确管理多个连接,因为当我在浏览器上打开新标签时,我总是收到消息" Connection#1",而不是" Connection#2" ,"连接#3" ...

错误在哪里?感谢

这是我的代码https://codeshare.io/a393M4 或者在这里:

#ifdef _WIN32
#include <WinSock2.h>
#define socket_t SOCKET
#else
#include <unistd.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#define WSACleanup()
#define INVALID_SOCKET (~0)
#define SOCKET_ERROR -1
#define closesocket close
#define ioctlsocket ioctl
#define socket_t int
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>



void print_time(char *buf, size_t buf_len) {
    time_t rawtime;
    time(&rawtime);
    struct tm info;
#ifdef _WIN32
    gmtime_s(&info, &rawtime);
#else
    gmtime_r(&rawtime, &info);
#endif

    const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
    const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

    snprintf(buf, buf_len, "%s, %i %s %i %02i:%02i:%02i GMT", days[info.tm_wday], info.tm_mday, months[info.tm_mon], 1900 + info.tm_year,
            info.tm_hour, info.tm_min, info.tm_sec);
}


typedef struct sock_list {
    socket_t s;
    struct sock_list *next;
} sock_list;


void sock_list_insert(sock_list **list, socket_t s) {
    sock_list *i = *list;
    sock_list *j = *list;
    sock_list *n = malloc(sizeof(sock_list));

    n->s = s;
    n->next = 0;

    while (i) {
        j = i;
        i = i->next;
    }

    if (j) {
        j->next = n;
    }
    else {
        *list = n;
    }
}


int sock_list_len(sock_list *list) {
    int c = 0;
    sock_list *i = list;
    while (i) {
        ++c;
        i = i->next;
    }
    return c;
}


int main() {
    int port = 80;

#ifdef _WIN32
    WSADATA wsa;
    if (WSAStartup(MAKEWORD(2,2), &wsa) != 0) {
        return -1;
    }
#endif

    socket_t sock;
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET) {
        printf("Cannot open socket (-2)\n");
        WSACleanup();
        return -2;
    }
    unsigned long mode = 1;
    ioctlsocket(sock, FIONBIO, &mode);  // set as non-blocking


    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(port);


    if (bind(sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
        printf("Cannot bind socket (-3)\n");
        closesocket(sock);
        WSACleanup();
        return -3;
    }


    listen(sock, SOMAXCONN);
    sock_list *conn_list = 0;


    for (;;) {

        sock_list *i = conn_list;
        fd_set set;
        FD_ZERO(&set);
        while (i) {
            FD_SET(i->s, &set);
            i = i->next;
        }
        select(0, &set, &set, &set, 0);


        struct sockaddr_in client;
        memset(&client, 0, sizeof(client));
        int c = sizeof(client);
        socket_t ns = accept(sock, (struct sockaddr *) &client, &c);
        if (ns != INVALID_SOCKET) {
            printf("new sock %u\n", ns);
            sock_list_insert(&conn_list, ns);
        }


        int count = 0;
        i = conn_list;
        while (i) {
            ++count;
            int recv_sz;
            char msg[4096];
            char tbuf[512];

            print_time(tbuf, 512);

            recv_sz = recv(i->s, msg, 4096, 0);

            if (recv_sz > 0) {
                char html[4096];

                snprintf(html, 4096, "<!DOCTYPE HTML><html><head><meta charset='utf-8'><title>Ciao</title>"
                                     "<style type='text/css'>body {margin: 200px auto;text-align: center;color: #393939;}</style>"
                                     "</head><body><h1>Connection %i</h1><h1>%s</h1></body></html>", count, tbuf);
                snprintf(msg, 4096, "HTTP/1.1 200 OK\r\nContent-Length: %i\r\nContent-Type: text/html; charset=utf-8\r\n\r\n%s",
                         strlen(html),
                         html);

                send(i->s, msg, strlen(msg), 0);
                printf("send to %u\n", i->s);

            }
            i = i->next;
        }

        fflush(stdout);
#ifdef _WIN32
        Sleep(1);
#else
        usleep(1000);
#endif
    }


    closesocket(sock);
    WSACleanup();


    return 0;
}

1 个答案:

答案 0 :(得分:0)

由于以下代码,'count'始终为1:

    int count = 0;
    i = conn_list;

    while (i)
    {
        ++count;

建议将'count'的初始化移到之前:

for (;;)

那为什么每次为每个新连接重写所有HTML页面呢?

我认为只有在找到新连接时才需要编写一个特定的HTML页面