【发布时间】:2021-08-05 23:26:25
【问题描述】:
我试图在 Windows 上编写一个简单的客户端服务器程序。我的服务器端代码如下所示。
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int main()
{
WSADATA WSAData;
SOCKET serverSock, clientSock;
SOCKADDR_IN serverAddr, clientAddr;
WSAStartup(MAKEWORD(2,0),&WSAData);
serverSock=socket(AF_INET,SOCK_STREAM,0);
serverAddr.sin_addr.s_addr=INADDR_ANY;
serverAddr.sin_family=AF_INET;
serverAddr.sin_port=htons(5555);
bind(serverSock,(SOCKADDR *)&serverAddr, sizeof(serverAddr));
listen(serverSock,0);
std::cout<<"Listening for incoming connections \n";
char buffer[1024];
//memset(buffer,0,sizeof(buffer));
int clientAddrsize= sizeof(clientAddr);
if(clientSock = ( accept(serverSock,(SOCKADDR *)&clientAddr, &clientAddrsize ) != INVALID_SOCKET) )
{
std::cout<<"Client connected \n";
recv(clientSock,buffer,int(strlen(buffer)),0);
std::cout<<"Client Says: " << buffer <<"\n" ;
Sleep(10000);
//memset(buffer,0,sizeof(buffer));
closesocket(clientSock);
closesocket(serverSock);
WSACleanup();
}
return 0;
}
客户端代码如下:
#include <iostream>
#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int main()
{
WSADATA WSAData;
SOCKET clientSock;
SOCKADDR_IN addr;
WSAStartup(MAKEWORD(2,0),&WSAData);
clientSock=socket(AF_INET,SOCK_STREAM,0);
addr.sin_addr.s_addr=inet_addr("127.0.0.1");
addr.sin_family=AF_INET;
addr.sin_port=htons(5555);
connect(clientSock,(SOCKADDR *)&addr,sizeof(addr));
std::cout <<"Connected to the server \n";
//memset(buffer,0,sizeof(buffer));
char buffer[1024]={'h','e','l','l','o','.','\0'};
send(clientSock,buffer,int(strlen(buffer)),0);
std::cout<<"Message sent \n" ;
Sleep(10000);
closesocket(clientSock);
WSACleanup();
std::cout<<"Socket closed \n";
return 0;
}
我在服务器端看到以下输出:
Listening for incoming connections
Client connected
Client Says: R☺
我期待的是Client Says: Hello.。不知道为什么我得到垃圾值。
谢谢
【问题讨论】:
-
“垃圾”值几乎总是取决于使用未初始化的数据(局部变量或数组元素);或者不添加、跳过或不计算字符串空终止符。
-
顺便说一下,
char buffer[1024]={'h','e','l','l','o','.','\0'};与char buffer[1024]="hello.";完全一样 -
您需要始终捕获 recv() 返回的值并对其进行适当的处理。如果不这样做,您将无法知道 recv() 实际写入本地缓冲区的字节数。 (它可能比您要求的字节少)
-
例如:
send(clientSock,buffer,int(strlen(buffer)),0);将不会发送buffer的空终止符。而recv(clientSock,buffer,int(strlen(buffer)),0);使用buffer的未初始化(因此是不确定的,或者如果你愿意的话是垃圾)内容来计算数组的大小。所以你有我之前列出的两个问题的组合。 -
另外,将 strlen(buffer) 作为 recv() 的最后一个参数传入没有多大意义,因为 strlen() 读取其参数指向的字节以查看字符串的长度,并且在您调用 recv() 时,尚未收到字符串,因此这是不可能的。您可能想要传递 sizeof(buffer) 。