Ser*_*iGS 3 c winsock winsockets winsock2
我正在学习Winsock和我在发送和接收一个简单的字符串时遇到一个奇怪的问题.这是我的代码(纯C):
//...
//Declarations and stuff
//----------- SEND SOME DATA -------------------------------------------------
char string1[] = "string-1";
int bytes_sent = 0;
bytes_sent = send(client_socket, string1, strlen(string1), 0);
printf("BYTES SENT: %i\n", bytes_sent);
printf("\n-----------------------------------------------\n\n");
system("pause");
//...
Run Code Online (Sandbox Code Playgroud)
//...
//Declarations and stuff
//----------- START LISTENING FOR REQUESTS ------------------------------------
SOCKET ClientSocket;
#define BUFFER_SIZE 256
int size;
struct sockaddr_in client_info;
char client_ip[16];
char data_received[BUFFER_SIZE];
int bytes_received = 0;
listen(ListenSocket, SOMAXCONN);
while(1){
ClientSocket = accept(ListenSocket, (struct sockaddr *)&client_info, &size);
strcpy(client_ip, inet_ntoa(client_info.sin_addr));
do{
bytes_received = recv(ClientSocket, data_received, BUFFER_SIZE, 0);
if(bytes_received > 0){
printf("DATA RECEIVED FROM %s: %s (%i bytes)\n", client_ip, data_received, bytes_received);
}
}while(bytes_received > 0);
printf("\n-----------------------------------------------\n\n");
}
//...
Run Code Online (Sandbox Code Playgroud)
问题是服务器打印我的字符串+一些奇怪的符号(见图).
我正在使用流套接字.这个例子非常简单,所以我不知道什么是错的.如果我随机修改字符串或服务器的缓冲区大小,或两者兼而有之,问题就会消失(服务器打印OK字符串).问题修复如果在send()调用中我使用sizeof()而不是strlen().我有点迷失在这里.如果我错过了什么,请善待,这是我在这里的第一篇文章.我可以提供整个代码(它基本上是winsock start和socket定义).
您发送的数据不包含终止空字符:
bytes_sent = send(client_socket, string1, strlen(string1), 0);
Run Code Online (Sandbox Code Playgroud)
...因为strlen不计算终止空值.这本身并不是问题,而是与接收方的事实相结合:
char data_received[BUFFER_SIZE];
// ...
bytes_received = recv(ClientSocket, data_received, BUFFER_SIZE, 0);
Run Code Online (Sandbox Code Playgroud)
data_received未初始化,您可以接收最多BUFFER_SIZE字节.这意味着,因为您发送的数据不是以空值终止的:
如果bytes_received < BUFFER_SIZE,其余部分data_received 可能未初始化,因此访问/打印将是未定义的行为.它实际上并非100%明确,因为文档说:
[...]调用recv将返回当前可用的数据 - 达到指定缓冲区的大小[...]
...所以这可能意味着缓冲区的其余部分保持不变.
bytes_received == BUFFER_SIZE没有null-terminator,那么printf将通过尝试打印它来调用未定义的行为,因为它不知道字符串停止的位置并将超出数组.解决这些问题的最简单方法是发送空终止符:
bytes_sent = send(client_socket, string1, strlen(string1)+1, 0); // +1 here
bytes_sent = send(client_socket, string1, sizeof(string1), 0); // same as above
Run Code Online (Sandbox Code Playgroud)
...或者接收较少的字节并将null终止符放在接收大小上:
bytes_received = recv(ClientSocket, data_received, BUFFER_SIZE-1, 0); // -1 here
data_received[bytes_received] = 0;
Run Code Online (Sandbox Code Playgroud)
我亲自去第一个.