Сообщение, переданное с сервера клиенту, не появляется - PullRequest
0 голосов
/ 09 июля 2020

Я пишу клиент-серверное приложение на C ++ (Visual Studio 2017) с использованием WinSock2. Посмотрел туториал YouTube, сделал сервер и клиент. При запуске соединение устанавливается. Но сообщение с сервера клиенту не передается.

Вот мой сервер.

//Server
#pragma comment(lib, "ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <iostream>

int main() {

    //WinSock Startup
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    if (WSAStartup(DllVersion, &wsaData) != 0) { //If WSAStartup returns anything ither than 0, than that means an error has occured in the WinSock Startup
        MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);
        exit(1);
    }

    SOCKADDR_IN addr; //Address tha the will bind our listening socket to
    int addrlen = sizeof(addr); //lenght of the address (required for accept call)
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //Broadcast locally
    addr.sin_port = htons(1111); //Port
    addr.sin_family = AF_INET; //IPv4 Socket

    SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
    bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); //Bind the address to the socket
    listen(sListen, SOMAXCONN); //Places sListen socket in a state in which is in listening for an incoming connection. Note: SOMAXCONN = Socket Outstanding Max Connections

    SOCKET newConnection; // Socket to hold the client's connection
    newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
    if (newConnection == 0) { //If accepting the client's connection failed
        std::cout << "Failed to accept the client's connection" << std::endl;
    }
    else { //If client connection properly accepted
        std::cout << "Client connected!" << std::endl;
        char MOID[256] = "Welcome! This is a Message of the Day."; //Create buffer with message of the day
        send(newConnection, MOID, sizeof(MOID), NULL); //Send MOID buffer
    }
    system("pause");
    return 0;
}

А вот такой клиент.

//Client
#pragma comment (lib, "ws2_32.lib")
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WinSock2.h>
#include <iostream>

int main() {

    //WinSock Startup
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    if (WSAStartup(DllVersion, &wsaData) != 0) { //If WSAStartup returns anything ither than 0, than that means an error has occured in the WinSock Startup
        MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR); 
        exit(1);
    }

    SOCKADDR_IN addr; //Address to be binded to our Connection socket
    int sizeofaddr = sizeof(addr); //Need sizeofaddr for the connect function
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //Address = localhoct (this pc)
    addr.sin_port = htons(1111); //Port =  1111
    addr.sin_family = AF_INET; //IPv4 Socket

    SOCKET Connection = socket(AF_INET, SOCK_STREAM, NULL); //Set connection socket
    if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) { //If we are unable to connect...
        MessageBoxA(NULL, "Failed to connect", "Error", MB_OK | MB_ICONERROR);
        return 0; //Failed to connect
    }
    std::cout << "Connected!" << std::endl;
    char MOID[256];
    recv(Connection, MOID, sizeof(MOID), NULL); //Recieve Message of the day  buffer into MOID array 
    std::cout << "MOID:" << std::endl;
    system("pause");

    return 0;
}

Это сообщение должно быть передано: «Добро пожаловать! Это сообщение дня». Подскажите пожалуйста, почему не передается сообщение и как это исправить?

1 Ответ

2 голосов
/ 09 июля 2020

Это сообщение должно быть передано: «Добро пожаловать! Это сообщение дня».

Ваше ожидание неверно. TCP-сокет - это потоковый сокет (как предлагается параметром SOCK_STREAM), что означает, что он имеет определенные свойства. Для потока это означает, что данные будут получены в том же порядке, в котором они были отправлены (или вы получите сообщение об ошибке). Однако никто не гарантирует, что вы получите все сообщение как один пакет. Вы можете получить их побайтово или группами по 2 байта, или целым сообщением или любым другим вариантом. Итак, ваша программа должна обрабатывать все это - читать данные в al oop, пока вы не получите все свое сообщение. Как вы узнаете, что все сообщение получено? Это зависит от вас - некоторые отправляют размер сообщения заранее, некоторые используют маркер конца сообщения (который может быть символом '\0' вашего сообщения). Но ожидать, что вы получите все сообщение одним выстрелом, просто неправильно, это не работает. В дополнение к этому вам нужно проверить, что возвращает recv() - ie сколько байтов он получил или произошла ли какая-либо ошибка.

...