Сокеты не отправляют данные - PullRequest
0 голосов
/ 09 июня 2019

В настоящее время я работаю над системой обмена мгновенными сообщениями, для которой между сервером и клиентом требуется связь. Я попробовал это в C ++, используя API сокета по умолчанию. Проблема в том, что даже если обе программы (сервер и клиент) скомпилированы нормально, не будет ни одного сокета, отправленного клиентом, который достигает сервера.

Я не знаю, что я здесь сделал неправильно (я просмотрел свой код примерно 5 раз и даже сделал это снова с нуля, но безуспешно). Я использовал сообщения «отладки», чтобы найти проблемы, и все они касаются циклов обработки, которые я использую.


// code from the server

#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <Ws2tcpip.h>
#include <string>

int main()
{
    std::locale::global(std::locale("fr-FR"));

    WSAData wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 
    {
        std::cout << "Error initializing winsock";
        return -1;
    }

    SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    if (server == INVALID_SOCKET)
    {
        std::cout << "Error initializing the socket ";
        return -2;
    }

    const unsigned short port = 9999;
    sockaddr_in addr;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port); 
    addr.sin_family = AF_INET; 

    int res = bind(server, (sockaddr*)&addr, sizeof(addr));
    if (res != 0)
    {
        std::cout << "Error when binding";
        return -3;
    }

    res = listen(server, SOMAXCONN);
    if (res != 0)
    {
        std::cout << "Error on calling listen";
        return -4;
    }

    std::cout << "Server successfully launched" << std::endl;

    char buffer[1025];

    while (true)
    {
        sockaddr_in from = { 0 };
        int addrlen = sizeof(from);
        SOCKET newClient = accept(server, (SOCKADDR*)(&from), &addrlen);

        if (newClient != SOCKET_ERROR) 
        {
            std::cout << "Client connected successfully" << std::endl;

            int Bytes = recv(newClient, buffer, 1024, 0);

            if (Bytes <= 0)
            {
                break;
            }

            std::cout << "Message received from client : " << buffer << std::endl;
            send(newClient, buffer, 1024, 0); // send it back to client
        }
    }
    return 0;
}


// code from the client 

#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <stdlib.h>
#include <iostream>
#include <thread>
#include <vector>
#include <Ws2tcpip.h>
#include <string>

#define _WINSOCK_DEPRECATED_NO_WARNINGS

void sendMessage(SOCKET s);
void recvMessage(SOCKET s);

int main()
{
    std::locale::global(std::locale("fr-FR"));

    WSAData wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) 
    {
        std::cout << "Error initializing winsock";
        return -1;
    }

    SOCKET server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (server == INVALID_SOCKET)
    {
        std::cout << "Error initializing the socket ";
        return -2;
    }

    sockaddr_in addr;
    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9999);

    int res = bind(server, (sockaddr*)&addr, sizeof(addr));
    if (res != 0)
    {
        std::cout << "Error when binding";
        return -3;
    }

    if (connect(server, (const sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
    {
        std::cout << "Erreur when connecting : " << WSAGetLastError() << std::endl;
        return -4;
    }

    std::cout << "You are connected to server" << std::endl;

    std::thread sending(sendMessage, server);
    std::thread receiving(recvMessage, server);

    sending.detach();
    receiving.detach();

    while (true)
    { }

    return 0;
}


void sendMessage(SOCKET s)
{
    while (true)
    {
        std::string buff;
        std::cout << "Type your message :" << std::endl;
        std::getline(std::cin, buff);
        std::cout << std::endl;

        int Bytes = send(s, buff.c_str(), 1024, 0);
        if (Bytes <= 0)
        {
            break;
        }
    }
}

void recvMessage(SOCKET s)
{
    while (true)
    {
        char buffer[1025];
        int Bytes = recv(s, buffer, 1024, 0);
        if (Bytes <= 0)
        {
            break;
        }

        std::cout << "The server sent : " << buffer << std::endl;
    }
}

Сервер должен отображать сообщение о том, что клиент подключился при запуске клиента, и отображает команду чата, но единственное, что отображается в консоли сервера, - это сообщение о том, что сервер запущен правильно ... Тем не менее, клиент отображает сообщение, предположительно «полученное» сервером.

PS: я знаю, что коду не нужно так много операторов "include", просто я не помню, какие из них содержали какие функции, поэтому я бы предпочел включить больше, чем недостаточно для тех, кто хочет скомпилировать код.

1 Ответ

1 голос
/ 09 июня 2019

Несколько вещей:

Во-первых, это неправильно:

send(s, buff.c_str(), 1024, 0)

Вы в основном говорите send, что буфер, к которому он обращается, составляет полный 1 КБ, и отправляет все это,Он не имеет ни малейшего представления о том, сколько памяти на самом деле является действительным, и ничего не знает о завершенных строках.

Во-вторых, установка клиента неверна.Не bind к клиентскому сокету;connect достаточно.Обратите внимание на следующее:

int res = bind(server, (sockaddr*)&addr, sizeof(addr));
if (res != 0)
{
    std::cout << "Error when binding";
    return -3;
}

if (connect(server, (const sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR)
{
    std::cout << "Erreur when connecting : " << WSAGetLastError() << std::endl;
    return -4;
}

Этой связи не должно быть.connect свяжется с сокетом, если соединение может быть установлено.Удаление клиентской секции привязки, исправление управления буфером и правильное размещение вызовов closesocket, и ваша программа будет намного дальше работать.Есть еще некоторые рабочие процессы логики вопроса, но, по крайней мере, подключение будет настроено лучше.

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