Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 客户端服务器回显聊天(多路复用I/O+线程)_C_Multithreading_Sockets_Server_Multiplexing - Fatal编程技术网

C 客户端服务器回显聊天(多路复用I/O+线程)

C 客户端服务器回显聊天(多路复用I/O+线程),c,multithreading,sockets,server,multiplexing,C,Multithreading,Sockets,Server,Multiplexing,我刚开始学习C语言,我正在尝试处理Windows套接字 问题是服务器只能接受和发送一次消息。 我使用了调试模式,看到工作在服务器部分的select中停止。这在客户端看起来很好,但我不确定,也没有看到代码中的问题。但我有这样一个结果。怎么了 我注意到我的tv.tv_秒没有定义,我在选择之前就这样做了,没有任何更改 当然,因为我需要接收和发送消息,所以我不需要在accept中写入描述符,对吗 客户端使用CreateThread函数,我尝试在其中发送消息。Send在main的while1循环中 服务器

我刚开始学习C语言,我正在尝试处理Windows套接字

问题是服务器只能接受和发送一次消息。 我使用了调试模式,看到工作在服务器部分的select中停止。这在客户端看起来很好,但我不确定,也没有看到代码中的问题。但我有这样一个结果。怎么了

我注意到我的tv.tv_秒没有定义,我在选择之前就这样做了,没有任何更改

当然,因为我需要接收和发送消息,所以我不需要在accept中写入描述符,对吗

客户端使用CreateThread函数,我尝试在其中发送消息。Send在main的while1循环中

服务器部件:

int main(int argc, char* argv[])
{
    /* definitions, WSAStartup(), socket(), bind(), listen() 
    Listening socket is a returned value of listen() function*/

        FD_ZERO(&readSet);
        FD_ZERO(&writeSet);

        while (1)
        {
            // SELECT (LISTENING SOCKET)
            FD_ZERO(&readSet);
            FD_SET(listeningSocket, &readSet);
            tv.tv_sec = 5;
            printf("Listening: Read FD: %d; Write FD : %d;\n", FD_ISSET(listeningSocket, &readSet), FD_ISSET(listeningSocket, &writeSet));
            if ((retVal = select(listeningSocket + 1, &readSet, NULL, NULL, 0)) == SOCKET_ERROR)
            {
                printf("Select error ");
                break;
            }
            else if (retVal == 0)
            {
                printf(". . .\n");
                continue;
            }
            else
            {
                // READ SD
                if ((FD_ISSET(listeningSocket, &readSet)) != SOCKET_ERROR)
                {
                    if ((newSocketDescriptor = accept(listeningSocket, (struct sockaddr *)&clientAddr, &clientAddrSize)) == SOCKET_ERROR)
                    {
                        printf("Accept error ");
                        break;
                    }
                    FD_ZERO(&readSet);
                    FD_SET(newSocketDescriptor, &readSet);

                    HOSTENT *hst = gethostbyaddr((const char *)&serverAddr.sin_addr.s_addr, 4, AF_INET);
                    printf("Welcome %s (%s:%d) new connected\n", hst->h_name, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));
                    printf("Read FD: %d; Write FD : %d;\n", FD_ISSET(newSocketDescriptor, &readSet), FD_ISSET(newSocketDescriptor, &writeSet));

                    // READ
                    if (FD_ISSET(newSocketDescriptor, &readSet) != 0)
                    {
                        if ((numBytes = recv(newSocketDescriptor, &bufferData[0], sizeof(bufferData), 0)) == SOCKET_ERROR)
                        {
                            printf("Recv failed \n");
                            freeSocketInformation(newSocketDescriptor);
                            break;
                        }

                        bufferData[numBytes] = '\0';
                        printf("Client -> Server: %s\n", &bufferData[0]);
                    }

                    // WRITE
                    FD_ZERO(&writeSet);
                    FD_SET(newSocketDescriptor, &writeSet);

                    printf("Read FD: %d; Write FD : %d;\n", FD_ISSET(newSocketDescriptor, &readSet), FD_ISSET(newSocketDescriptor, &writeSet));
                    if (FD_ISSET(newSocketDescriptor, &writeSet) != 0)
                    {
                        //fgets(&bufferData[0], sizeof(bufferData), stdin);
                        if (send(newSocketDescriptor, &bufferData[0], strlen(&bufferData[0]), 0) == SOCKET_ERROR)
                        {
                            printf("Send error ");
                            freeSocketInformation(newSocketDescriptor);
                            break;
                        }
                        bufferData[numBytes] = '\0';
                        printf("Server -> Client: %s\n", &bufferData[0]);

                    }
                    printf("Read FD: %d; Write FD : %d;\n", FD_ISSET(newSocketDescriptor, &readSet), FD_ISSET(newSocketDescriptor, &writeSet));

                    FD_SET(newSocketDescriptor, &readSet);
                }
            }
        }
        //FD_CLR(listeningSocket, &readSet);
        closesocket(newSocketDescriptor);
    } while (FALSE);
    printf("- Error code: %d\n", WSAGetLastError());
    closesocket(listeningSocket);
    WSACleanup();
    return 0;
}
客户端部分它使用代码末尾的CreateThread函数:

/* definitions, socket(), connect()*/
        if (ioctlsocket(socketDescriptor, FIONBIO, (unsigned long *)&nb) != 0)
        {
            printf("ioctlsocket error ");
            break;
        }


            FD_ZERO(&writeSet);
            FD_SET(socketDescriptor, &writeSet);
            if ((retVal = select(socketDescriptor + 1, NULL, &writeSet, NULL, &tv)) == SOCKET_ERROR)
            {
                printf("Send non-blocking error ");
                break;
            }
            else if (retVal == 0)
            {
                printf("Non-blocking connect time limit is expired");
                break;
            }
        }
        printf("Connection with %s\n", SERVERADDR);

        DWORD thID;
        printf("Socket Desciptor: %d\n", socketDescriptor);
        HANDLE hThread = CreateThread(NULL, NULL, HandleReadThread, (LPVOID)socketDescriptor, NULL, &thID);
        printf("Thread ID: %d\n", thID);

        while (1)
        {
            // WRITE
            printf("Client -> Server: ");
            fgets(&bufferData[0], sizeof(bufferData), stdin);

            FD_ZERO(&writeSet);
            FD_SET(socketDescriptor, &writeSet);
            tv.tv_sec = 5;
            if ((retVal = select(socketDescriptor + 1, NULL, &writeSet, NULL, &tv)) == SOCKET_ERROR)
            {
                printf("Send non-blocking error ");
                break;
            }
            if (FD_ISSET(socketDescriptor, &writeSet) != 0)
            {
                if (send(socketDescriptor, bufferData, strlen(&bufferData[0]), 0) == SOCKET_ERROR)
                {
                    printf("Send error ");
                    break;
                }
            }
        }
    } while (FALSE);
    printf("- Error code: %d\n", WSAGetLastError());
    closesocket(socketDescriptor);
    WSACleanup();
    return 0;
}

DWORD WINAPI HandleReadThread(LPVOID serverSocket)
{
    SOCKET socketDescriptor;
    socketDescriptor = (SOCKET)serverSocket;
    char bufferData[MAXDATASIZE] = { 0 };
    int retVal;
    fd_set readSet;
    timeval tv = { 0 };
    tv.tv_sec = 5;

    int numBytes;
    int nclients = 0;

    while (1)
    {
        FD_ZERO(&readSet);
        FD_SET(socketDescriptor, &readSet);

        if ((retVal = select(socketDescriptor + 1, &readSet, NULL, NULL, &tv)) == SOCKET_ERROR)
        {
            printf("Select error. Error code: %d", WSAGetLastError());
            break;
        }
        else if (retVal == 0)
        {
            //printf(". . .\n");
            continue;
        }

        else
        {
            //FD_ZERO(socketDescriptor, &readSet);
            //FD_SET(socketDescriptor, &readSet);
            // READ
            if (FD_ISSET(socketDescriptor, &readSet) != 0)
            {
                if ((numBytes = recv(socketDescriptor, &bufferData[0], sizeof(bufferData), 0)) == SOCKET_ERROR)
                {
                    printf("Recv error in Thread. Error code: %d\n", WSAGetLastError());
                    break;
                }
                printf("\nSocket Desciptor: %d\n", socketDescriptor);
                bufferData[numBytes] = '\0';
                printf("Server -> Client: %s\n", &bufferData[0]);
            }
        }
    }
    closesocket(socketDescriptor);
    return 0;
}

我自己解决的。状况

if ((FD_ISSET(listeningSocket, &readSet)) != 0) 
工作了一个周期,应该在接受功能后完成。 此外,我还在while1开头的readSet的FD_SET之后添加了以下几行:

if (newSocketDescriptor)
{
    FD_SET(newSocketDescriptor, &readSet);
}

聊天开始工作,但是有很多东西需要处理:

do{…}while FALSE;对于FALSE的偏心非零值,仅用作无限循环。使用TRUE而不是FALSE,或1,或…是的,它只是用于从错误消息中取出并查看错误代码,因为每次在每个错误消息中都不写入WSAGetLastError,它不涉及逻辑。哦,我明白了。对打扰这意味着有很多代码需要处理,而我的机器没有WSA*函数。你确定这是一个MCVE吗?有一个完整的代码,我希望我尽量减少它,以了解发生了什么:谢谢!