multiplexing server with select() : accept() happening two times

我是研究僧i 提交于 2020-06-09 07:11:10

问题


I'm currently doing a school project for making http server. This server should be implemented by multiplexing, but socket programming is totally new area for me. So I made simple server to understand better of server but it doesn't work as I intended...


int main()
{
    int server_socket, new_socket;
    struct sockaddr_in server_address, new_address;
    socklen_t new_len = sizeof(new_address);
    const char *hello = "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: 12\n\nHello world!"; // simple respond to client

    // make server socket
    server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    // turn server socket into non block fd
    fcntl(server_socket, F_SETFL, O_NONBLOCK);

    FD_ZERO(&read_set);
    FD_ZERO(&write_set);
    FD_ZERO(&temp_set);
    FD_SET(server_socket, &temp_set);
    int fd_max = server_socket;

    // bind address to server_socket and listen
    bind(server_socket, (struct sockaddr *)&server_address, sizeof(server_address);
    listen(server_socket, 1000);

    // setting fd_set variable for select()
    fd_set read_set, write_set, temp_set;
    FD_ZERO(&read_set);
    FD_ZERO(&write_set);
    FD_ZERO(&temp_set);
    // add server_socket into temp_set
    FD_SET(server_socket, &temp_set);

    // set container for having all the fds
    std::set<int> curfds, tmpfds;
    tmpfds.insert(server_socket);
    int fd_max = server_socket;

    // start server
    while(1) {
        curfds = tmpfds;
        fd_max = *curfds.rbegin();
        read_set = temp_set;
        write_set = temp_set;

        // setting timedelay 0
        struct timeval timeout;
        timeout.tv_sec = 0;
        timeout.tv_usec = 0;

        select(fd_max + 1, &read_set, &write_set, NULL, &timeout);

        // check which fd is activated
        for (std::set<int>::iterator it = curfds.begin(); it != curfds.end(); ++it)
        {
            if (FD_ISSET(*it, &read_set) > 0) 
            {
                // if server_socket is updated
                if (*it == server_socket)
                {
                    // accept client connection
                    new_socket = accept(*it, (sockaddr *)&new_address, &new_len);
                    // turn new_socket into non block
                    fcntl(new_socket, F_SETFL, O_NONBLOCK);
                    // update temp_set and tmpfds
                    FD_SET(new_socket, &temp_set);
                    tmpfds.insert(new_socket);
                    printf("client connected\n");
                }
                else // client socket
                {
                    printf("ready to read from client\n");
                    char buff[1001];
                    int res = read(*it, buff, 1000);
                    buff[res] = 0;

                    // if i finished to read all http request
                    if (res == 0) 
                    {
                        // check client is ready to be written
                        if (FD_ISSET(*it, &write_set) > 0) {
                            write(*it, hello, strlen(hello));
                        }
                        // deconnect
                        FD_CLR(*it, &temp_set);
                        close(*it);
                        tmpfds.erase(*it);
                    }
                }
            }
        }
        // for debugging loop
        sleep(1);
        printf("finished one rotation\n");
    } // while
    close(server_socket);
    return 0;
}

I omitted checking error (checking return -1 every time by calling function select(), write(), read(), etc...) on purpose in this code for making easy to read.

And this is result.

finished one rotation
finished one rotation
finished one rotation
finished one rotation
finished one rotation
finished one rotation
client connected // <-- client connected
finished one rotation
client connected // <-- client connected again ??
ready to read from client
finished one rotation
...

problem 1. When I tried to "one time" connect from web browser, It shows two times connection message. Moreover, second connection happened after first select(). Why select() didn't update server_socket after accept() ??

problem 2. I can't send http response to client. It shows message "ready to read from client" but my web browser wait for server response infinitely....

Could you please explain me what happen on my server ? Thanks in advance.

来源:https://stackoverflow.com/questions/61965186/multiplexing-server-with-select-accept-happening-two-times

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!