C++ 在客户端-服务器通信c+中接收到垃圾值+;
我试图在windows上编写一个简单的客户机-服务器程序。我的服务器端代码如下所示C++ 在客户端-服务器通信c+中接收到垃圾值+;,c++,windows,sockets,C++,Windows,Sockets,我试图在windows上编写一个简单的客户机-服务器程序。我的服务器端代码如下所示 #include <iostream> #include <windows.h> #include <winsock2.h> #include <stdlib.h> #include <stdio.h> using namespace std; int main() { WSADATA WSAData; SOCKET serverSo
#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;
}
我所期待的是客户说:你好。
。不知道为什么我会得到垃圾值
谢谢
这将在自动作用域中声明一个本地char
数组。数组没有初始化任何内容,并且包含随机垃圾
recv(clientSock,buffer,int(strlen(buffer)),0);
这将缓冲区
传递到strlen
。然而,buffer
包含垃圾,这是未定义的行为,最终的结果可能是,随机的,立即崩溃,在这一点上,或者从strlen
返回一些奇怪的值
此外,recv
的返回值完全被忽略,根本不检查
所有套接字系统调用都可能失败,每个套接字系统调用、send
、recv
,以及所有其他调用都可能失败。此外,即使成功,recv
也不能保证一次发送的所有内容都将在一次发送中recv
ed
例如,如果send
sent 10个字节,则对recv
的第一次调用可能返回1或5,这表示只有前一个或五个字节立即被recv
ed。您不能保证recv
会一次全部接收到这10个字节。否则,recv
显然需要再次调用以接收消息的其余部分
为了拥有可靠的客户机/服务器应用程序,您需要解决所有这些问题:
recv
我所说的一切也适用于send
。尝试send
10个字节可能返回7个字节,这表示只发送了前7个字节,然后您必须实现适当的逻辑来发送剩余的字节
“垃圾”值几乎总是依赖于使用未初始化的数据(局部变量或数组元素);或者不添加、跳过或不计算字符串空终止符代码>与字符缓冲区[1024]=“您好。”代码>您需要始终捕获recv()返回的值并对其进行适当的操作。如果不知道,则无法知道recv()实际写入本地缓冲区的字节数。(可能比您请求的字节少)例如:
send(clientSock,buffer,int(strlen(buffer)),0)
不会发送缓冲区的空终止符
。和recv(clientSock,buffer,int(strlen(buffer)),0)
使用缓冲区的未初始化内容(因此不确定,如果您愿意,也可以使用垃圾)来计算数组的大小。因此,我前面列出的两个问题都存在。另外,将strlen(buffer)作为最后一个参数传递给recv()没有多大意义,因为strlen()读取其参数指向的字节以查看字符串的长度,而在调用recv()时,字符串尚未收到,因此这是不可能的。您可能希望传递sizeof(缓冲区)。感谢@Sam提供详细信息。非常感谢。你能告诉我一些关于这个的实际实现吗?在这里,我可以看到关于如何处理由brotobuf序列化并发送的数据的参考代码。或者任何有意义的数据交换示例,这样我就可以从中吸取教训,或者给我指一个教程。在互联网上,大多数人没有显示如何正确处理和读取TCP数据包。我同意:不能从C语言、C++或任何技术编程主题中找到随机数据,或者一些小丑上传到YouTube的随机视频。学习高级技术主题的唯一方法是借助好的教科书。经典的教科书是史蒂文斯的《Unix网络编程》,但我认为它到现在已经有点过时了。但是,如果你搜索这本书,你应该找到一些其他相当好的书作为参考。
Listening for incoming connections
Client connected
Client Says: R☺
char buffer[1024];
recv(clientSock,buffer,int(strlen(buffer)),0);