Server Send()无法正确使用Select()

时间:2015-03-03 19:21:38

标签: c select client server winsock

我在我的服务器上使用select()以便它可以同时处理多个客户端,它可以使用带有recv()调用的select()一次性接收来自所有客户端的信息,但是当我想要使用带有send()的select()将信息发送到多个客户端,它不会一次发送到多个客户端。一旦工作客户端退出下一个客户端被处理,它将发送给一个客户端,其余客户端被阻止。我的select()逻辑错了吗?

fd_set master;    // master file descriptor list
fd_set read_fds;  // temp file descriptor list for select()
fd_set write_fds;  // temp file descriptor list for select()
int fdmax;        // maximum file descriptor number

int newfd;        // newly accept()ed socket descriptor
struct sockaddr_storage remoteaddr; // client address
socklen_t addrlen;

FD_ZERO(&master);    // clear the master and temp sets
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);

result = NULL;
recvbuflen = DEFAULT_BUFLEN;

memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;

// Resolve the server address and port
funcRtrnVal = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if (funcRtrnVal != 0) {
    printf("getaddrinfo failed with error: %d\n", funcRtrnVal);
        WSACleanup();
}

// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);

// add the listener to the master set
FD_SET(ListenSocket, &master);

// keep track of the biggest file descriptor
fdmax = ListenSocket; // so far, it's this one

    if (ListenSocket == INVALID_SOCKET) {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
    }

// Setup the TCP listening socket
funcRtrnVal = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);

// error check 'bind'
    if (funcRtrnVal == SOCKET_ERROR) {
        printf("bind failed with error: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
    }

freeaddrinfo(result);

// listen for incoming connections
funcRtrnVal = listen(ListenSocket, SOMAXCONN);

// error check 'listen'
    if (funcRtrnVal == SOCKET_ERROR) {
        printf("listen failed with error: %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        WSACleanup();
    }

while (true)
{
    read_fds = master; // copy it
    write_fds = master;

    // run select statement
    if (select(fdmax + 1, &read_fds, &write_fds, NULL, NULL) == -1)
    {
        //perror("select");
        //exit(4);
    }

    // run through the existing connections looking for data to read/write
    for (int i = 0; i <= fdmax; i++)
    {
        if (FD_ISSET(i, &read_fds))
        {
            printf("read triggered\n");

            if (i == ListenSocket)
            {
                // Accept a client socket
                newfd = accept(ListenSocket, NULL, NULL);

                // error check 'accept'
                    if (newfd == INVALID_SOCKET) {
                        printf("accept failed with error: %d\n", WSAGetLastError());
                        closesocket(ListenSocket);
                        WSACleanup();
                    }

                if (newfd == -1) {
                    //perror("accept");
                }
                else
                {
                    FD_SET(newfd, &master); // add to master set

                    if (newfd > fdmax) {    // keep track of the max
                        fdmax = newfd;
                    }
                }
            }

            else
            {
                // Receive from client
                funcRtrnVal = recv(i, recvbuf, recvbuflen, 0);

                // if we received a byte stream
                if (funcRtrnVal > 0)
                {
                    // get the length of the byte stream
                    int messageLength = (int)strlen(recvbuf);

                    printf("%s\n", recvbuf);

                }

                // empty out all the buffs
                memset(recvbuf, 0, sizeof(recvbuf));

                //close(i); // bye!
                //FD_CLR(i, &master); // remove from master set
            }
        }

        if (FD_ISSET(i, &write_fds))
        {
            printf("write triggered\n");

            // Send the data to the client
            funcRtrnVal = send(i, sendbuf, (int)strlen(sendbuf), 0);

            if (funcRtrnVal > 0)
            {
                printf("Server sent sendbuf: %s\n", sendbuf);

                // empty out the sendbuf
                memset(sendbuf, 0, sizeof(sendbuf));
            }
        }
    } 
} 

0 个答案:

没有答案