Сервер не получает более 1 сообщения от клиента (программирование многопоточных сокетов) - PullRequest
0 голосов
/ 10 мая 2018

Я только начал с программирования сокетов и просто пытаюсь разрешить клиентам отправлять данные на сервер через TCP-соединение.Затем сервер отправит данные одному фиксированному клиенту, который просто отобразит их.

Я подумал, что это не будет слишком сложно.После того, как я настроил сервер и клиент, который отображает только отправленные данные, я создал несколько клиентов, использующих PuTTY для отправки некоторых данных на сервер, и все прошло отлично.Сервер пересылал сообщения, а фиксированный клиент отображал их.Но теперь, когда я закодировал этих «отправляющих клиентов», я могу заставить одного из этих клиентов отправить только одно сообщение, и после этого все «застряло».Там нет сообщения об ошибке или что-нибудь.Как только я отправляю второе сообщение, консоль не запрашивает у меня третьего сообщения.Я могу только закрыть клиентов и все.

Вот код для клиентов, которые просто отправляют данные:

#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");
}

Может кто-нибудь сказать мне, что я пропустил?Я уже провел два дня, выясняя, что здесь не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...