C++ 从服务器传输到客户端的消息不会出现

C++ 从服务器传输到客户端的消息不会出现,c++,winsock2,C++,Winsock2,我正在使用WinSock2用C++(Visual Studio 2017)编写一个客户机-服务器应用程序。我看了YouTube教程,制作了一个服务器和客户端。启动后,将建立连接。 但是来自服务器的消息不会传输到客户端 这是我的服务器 //Server #pragma comment(lib, "ws2_32.lib") #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <WinSock2.h> #include &l

我正在使用WinSock2用C++(Visual Studio 2017)编写一个客户机-服务器应用程序。我看了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;
}
//服务器
#pragma注释(lib,“ws2_32.lib”)
#定义\u WINSOCK\u不推荐\u无\u警告
#包括
#包括
int main(){
//WinSock启动
WSAData WSAData;
单词DllVersion=MAKEWORD(2,1);
如果(WSAStartup(DllVersion,&wsaData)!=0){//如果WSAStartup返回的值大于0,则表示WinSock启动时发生错误
MessageBoxA(NULL,“WinSock启动失败”,“错误”,MB|U OK | MB|U ICONERROR);
出口(1);
}
SOCKADDR\u IN addr;//将侦听套接字绑定到的地址
int addrlen=sizeof(addr);//地址的长度(接受呼叫所需)
addr.sin_addr.s_addr=inet_addr(“127.0.0.1”);//本地广播
addr.sin_port=htons(1111);//端口
addr.sin\u family=AF\u INET;//IPv4套接字
SOCKET sListen=SOCKET(AF_INET,SOCK_STREAM,NULL);//创建套接字以侦听新连接
绑定(sListen,(SOCKADDR*)&addr,sizeof(addr));//将地址绑定到套接字
侦听(sListen,SOMAXCONN);//将sListen套接字置于侦听传入连接的状态。注意:SOMAXCONN=套接字未完成的最大连接数
SOCKET newConnection;//用于保存客户端连接的套接字
newConnection=accept(sListen,(SOCKADDR*)&addr,&addrlen);//接受新连接
if(newConnection==0){//如果接受客户端的连接失败
标准::cout
这个信息应该被传递:“欢迎!这是今天的信息。”

您的期望是错误的。TCP套接字是一个流套接字(如SOCK_stream参数所建议的),这意味着它具有某些属性。对于stream,这意味着数据将以与发送相同的顺序接收(或者您收到错误)。但没有人保证您将以一个数据包的形式获得整个消息。您可以一个字节一个字节或两个字节的组,或整个消息或任何其他变体。因此,您的程序应该处理其中的任何一个—在获得整条消息之前在循环中读取数据。您如何知道收到了整条消息?这取决于您—某些人发送消息在此之前,有些人会使用消息结尾标记(可能是消息的
'\0'
符号)。但期望您在一次拍摄中获得整个消息是错误的,这样做不起作用。此外,您需要检查
recv()
返回的内容,即它接收了多少字节或是否发生了任何错误

这个信息应该被传递:“欢迎!这是今天的信息。”


您的期望是错误的。TCP套接字是一个流套接字(如SOCK_stream参数所建议的),这意味着它具有某些属性。对于stream,这意味着数据将以与发送相同的顺序接收(或者您收到错误)。但没有人保证您将以一个数据包的形式获得整个消息。您可以一个字节一个字节或两个字节的组,或整个消息或任何其他变体。因此,您的程序应该处理其中的任何一个—在获得整条消息之前在循环中读取数据。您如何知道收到了整条消息?这取决于您—某些人发送消息在此之前,有些人会使用消息结尾标记(可能是消息的
'\0'
符号)。但期望您在一次拍摄中获得整个消息是错误的,这样做不起作用。除此之外,您还需要检查
recv()
返回-即它接收了多少字节或是否发生了任何错误。

会发生什么?在客户端,我必须写
std::cout会发生什么?在客户端,我必须写
std::cout感谢您的解释。在我的情况下,一切都变得更简单:在
cout
中,我没有指定MOID数组如果我刚刚签名。@e7min在TCP中,不能保证
send(newConnection,MOID,sizeof(MOID),NULL);
将一次性发送整个
MOID
,或者
recv(Connection,MOID,sizeof(MOID),NULL)
将接收整个
MOID
。您忽略返回值,返回值告诉您实际发送/接收了多少字节。如果返回值
,则必须调用
send()
/
recv()
关于剩余的字节,这里有很多关于StackOverflow的问题,其他地方也有详细的教程。感谢您的解释。在我的例子中,一切都变得更简单:在
cout
中,我没有指定MOID数组本身,我只是对它进行了签名。@e7min在TCP中,不能保证
发送(newConnection,MOID,sizeof(MOID),NULL);
将一次性发送整个
MOID
,或者
recv(Connection,MOID,sizeof(MOID),NULL)
将接收整个
MOID
。您忽略返回值,返回值告诉您实际发送/接收了多少字节。如果返回值
然后您必须再次调用
send()
/
recv()
以获取剩余的字节。关于StackOverflow的问题很多,其他地方的教程也有详细介绍。
//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;
}