服务器没有从客户端收到多条消息(线程套接字编程)

时间:2018-05-10 12:09:25

标签: c++ sockets tcp client-server

我刚开始使用套接字编程,而我只是试图让客户端通过TCP连接将数据发送到服务器。然后,服务器将数据转发到一个固定客户端,该客户端只是显示它。

我认为这不会太难。在我设置服务器和仅显示已发送数据的客户端后,我使用PuTTY创建了多个客户端,将一些数据发送到服务器,一切正常。服务器转发消息,固定客户端显示消息。但是现在我已经编写了那些"发送客户端",我只能让其中一个客户端发送一条消息,之后一切都被"卡住了#34;。没有错误消息或任何内容。一旦我发送第二条消息,控制台就不会提示我给它第三条消息。我只能关闭客户和那个客户。

这里是简单发送数据的客户端的代码:

#include <iostream>
#include <string>
#include <WS2tcpip.h>
#pragma comment(lib, "ws2_32.lib")


void main()
{
    std::string ipAddress = "127.0.0.1";            
    int port = 54000;                       

    WSAData data;
    WORD ver = MAKEWORD(2, 2);
    int wsResult = WSAStartup(ver, &data);
    if (wsResult != 0)
    {
        std::cerr << "Can't start Winsock, Err #" << wsResult << std::endl;
        return;
    }

    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET)
    {
        std::cerr << "Can't create socket, Err #" << WSAGetLastError() << std::endl;
        WSACleanup();
        return;
    }

    sockaddr_in hint;
    hint.sin_family = AF_INET;
    hint.sin_port = htons(port);
    inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);

    int connResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
    if (connResult == SOCKET_ERROR)
    {
        std::cerr << "Can't connect to server, Err #" << WSAGetLastError() << std::endl;
        closesocket(sock);
        WSACleanup();
        return;
    }

    char buf[4096];
    std::string userInput;

    do
    {
        std::cout << "> ";
        std::getline(std::cin, userInput);

        if (userInput.size() > 0) {     
            int sendResult = send(sock, userInput.c_str(), userInput.size() + 1, 0);
            if (sendResult != SOCKET_ERROR)
            {
                ZeroMemory(buf, 4096);
                int bytesReceived = recv(sock, buf, 4096, 0);
                if (bytesReceived > 0)
                {
                    std::cout << "SERVER> " << std::string(buf, 0, bytesReceived) << std::endl;
                }
            }
        }

    } while (userInput.size() > 0);

    closesocket(sock);
    WSACleanup();
}

这是客户端的代码,应该只显示其他客户端发送的内容:

#include <iostream>
#include <ws2tcpip.h>
#include <string>

#pragma comment(lib, "ws2_32.lib")

void main() {

    std::string ipAddress = "127.0.0.1"; 
    int port = 54000;               


    WSAData data;
    WORD version = MAKEWORD(2, 2);
    int wsResult = WSAStartup(version, &data);
    if (wsResult != 0) {

        std::cerr << "Can't start Winsock, Err #" << wsResult << std::endl;
        return;
    }

    SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock == INVALID_SOCKET) {

        std::cerr << "Can't create socket, Err #" << WSAGetLastError() << std::endl;
    }

    sockaddr_in hint;
    hint.sin_family = AF_INET;
    hint.sin_port = htons(port); 
    inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);

    int connResult = connect(sock, (sockaddr *)&hint, sizeof(hint));
    if (connResult == SOCKET_ERROR) {

        std::cerr << "Can't connect to server, Err #" << WSAGetLastError() << std::endl;
        closesocket(sock);
        WSACleanup();
        return;
    }

    char buf[4096];

    do {

        ZeroMemory(buf, 4096);
        int bytesReceived = recv(sock, buf, 4096, 0);
        if (bytesReceived > 0) {

            std::cout << "SERVER> " << std::string(buf, 0, bytesReceived) << std::endl;
        }
    } while (true);

    closesocket(sock);

    WSACleanup();

}

这是应该能够处理多个客户端的服务器代码:

#include <iostream>
#include <WS2tcpip.h>
#include <string>

#pragma comment (lib, "ws2_32.lib")


void main()
{
    WSADATA wsData;
    WORD ver = MAKEWORD(2, 2);

    int wsOk = WSAStartup(ver, &wsData);
    if (wsOk != 0)
    {
        std::cerr << "Can't Initialize winsock! Quitting" << std::endl;
        return;
    }

    SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
    if (listening == INVALID_SOCKET)
    {
        std::cerr << "Can't create a socket! Quitting" << std::endl;
        return;
    }

    sockaddr_in hint;
    hint.sin_family = AF_INET;
    hint.sin_port = htons(54000);
    hint.sin_addr.S_un.S_addr = INADDR_ANY; 

    bind(listening, (sockaddr*)&hint, sizeof(hint));

    listen(listening, SOMAXCONN);

    fd_set master;
    FD_ZERO(&master);

    FD_SET(listening, &master);

    while (true)
    {
        fd_set copy = master;

        int socketCount = select(0, &copy, nullptr, nullptr, nullptr);

        for (int i = 0; i < socketCount; i++)
        {
            SOCKET sock = copy.fd_array[i];
            if (sock == listening)
            {
                SOCKET client = accept(listening, nullptr, nullptr);

                FD_SET(client, &master);

                std::string joinMsg = "Client joined\r\n";
                send(client, joinMsg.c_str(), joinMsg.size() + 1, 0);
            }
            else
            {
                char buf[4096];
                ZeroMemory(buf, 4096);

                int bytesIn = recv(sock, buf, 4096, 0);
                if (bytesIn <= 0)
                {
                    closesocket(sock);
                    FD_CLR(sock, &master);
                }
                else
                {

                    for (int i = 0; i < master.fd_count; i++)
                    {
                        SOCKET outSock = master.fd_array[i];
                        if (outSock != listening && outSock != sock)
                        {
                            send(outSock, buf, bytesIn, 0);
                        }
                    }
                }
            }
        }

    }


    WSACleanup();

    system("pause");
}

有人可以告诉我我错过了什么吗?我已经花了两天时间搞清楚,这里有什么问题。

0 个答案:

没有答案