[英]send() or recv() not syncing up
I've been doing the Winsock tutorials and following it exactly. 我一直在做Winsock教程并严格按照它进行操作。 I can't seem to get either send()
or recv()
to function properly. 我似乎无法使send()
或recv()
正常运行。 I have a basic Server and Client program set up, and the connection is being made, but the Server isn't sending a message to the Client. 我已经设置了基本的服务器和客户端程序,并且正在建立连接,但是服务器没有向客户端发送消息。 Using the Telnet client also doesn't receive a response from the server. 使用Telnet客户端也不会收到服务器的响应。 I'm not really sure what's happening, and all the questions I looked at were not basic or had stuff I couldn't really understand what they were doing. 我不是很确定发生了什么,我所看到的所有问题都不是基本问题,也不是我无法真正理解他们在做什么。
#include<WinSock2.h>
#include <io.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib") //winsock library
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
sockaddr_in server, client;
int c;
char *message;
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
else
printf("Initialised.\n");
//create a socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
return 2;
}
else
printf("Socket created.\n");
//prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.S_un.S_addr = INADDR_ANY;
server.sin_port = htons(8888);
//bind the socket
if (bind(s, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : &d", WSAGetLastError());
return 3;
}
else
puts("Bind done");
//listen
listen(s, 3);
//accept an incoming connection
puts("Waiting for incoming connections...");
c = sizeof(sockaddr_in);
while (new_socket = accept(s, (sockaddr *)&client, &c) != INVALID_SOCKET)
{
printf("Connect successful...\n");
//reply to the client
message = "Hello Client, I have recieved your connection, but I have to go now, bye!\n";
send(new_socket, message, strlen(message), 0);
puts("Message sent.\n");
}
if (new_socket == INVALID_SOCKET)
{
printf("accept() failed with error code : %d", WSAGetLastError());
return 4;
}
//close the socket
closesocket(s);
WSACleanup();
return 0;
}
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <IPHlpApi.h>
#include <stdio.h>
#pragma comment(lib, "Ws2_32.lib")
int main(int argc, char *argv[])
{
//intialize variables
WSADATA wsa;
char ip[100] = "192.168.1.117";
SOCKET s;
sockaddr_in server;
char *message, server_reply[75];
int recv_size;
//initialize Winsock
printf("\nInitialising Winsock...\n");
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
printf("Failed. Error Code : %d", WSAGetLastError());
return 1;
}
printf("Initialised.\n");
//create the socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket : %d", WSAGetLastError());
return 3;
}
printf("Socket created.\n");
server.sin_addr.S_un.S_addr = inet_addr(ip);
server.sin_family = AF_INET;
server.sin_port = htons(8888);
//connect to the server
if (connect(s, (sockaddr *)&server, sizeof(server)) < 0)
{
puts("connect error");
return 4;
}
else
{
printf("Connect successful");
recv_size = recv(s, server_reply, 75, 0);
}
if (recv_size <= 0)
{
puts("recv() failed\n");
}
else
{
//add a NULL terminating character to make it a proper string before printing
server_reply[recv_size] = '\0';
puts(server_reply);
}
getchar();
//close the socket
closesocket(s);
WSACleanup();
return 0;
}
The client also fails to print the "recv() failed"
line; 客户端也无法打印"recv() failed"
行; it's like it's stuck at the recv()
call. 就像卡在recv()
调用上一样。
On the server side: 在服务器端:
you are not checking the return value of listen()
for error. 您没有检查listen()
的返回值是否有错误。
you are not resetting c
on each call to accept()
, and you are not calling closesocket()
on each client that is accepted. 您没有在每次对accept()
调用上重置c
,也没有在每个被接受的客户端上调用closesocket()
。
you are not checking the return value of send()
for error. 您没有检查send()
的返回值是否有错误。
Try this instead: 尝试以下方法:
#include <WinSock2.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib") //winsock library
int main(int argc, char *argv[])
{
WSADATA wsa;
SOCKET s, new_socket;
sockaddr_in server, client;
int c, res, messagelen;
const char *message;
printf("\nInitializing Winsock...");
res = WSAStartup(MAKEWORD(2,2), &wsa);
if (res != 0)
{
printf("Failed. Error: %d\n", res);
return 1;
}
printf("Initialized.\n");
//create a socket
if((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf("Could not create socket. Error: %d\n", WSAGetLastError());
return 2;
}
printf("Socket created.\n");
//prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.S_un.S_addr = INADDR_ANY;
server.sin_port = htons(8888);
//bind the socket
if (bind(s, (sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed. Error: &d", WSAGetLastError());
return 3;
}
printf("Bind done.\n");
//listen
if (listen(s, 3) == SOCKET_ERROR)
{
printf("Listen failed. Error: &d", WSAGetLastError());
return 4;
}
printf("Listening.\n");
//accept incoming connections
printf("Waiting for incoming connections...\n");
do
{
c = sizeof(sockaddr_in);
new_socket = accept(s, (sockaddr *)&client, &c);
if (new_socket == INVALID_SOCKET)
{
printf("Failed to accept a client. Error: %d\n", WSAGetLastError());
return 5;
}
printf("Client connected...\n");
//reply to the client
message = "Hello Client, I have received your connection, but I have to go now, bye!\n";
messagelen = strlen(message);
do
{
res = send(new_socket, message, messagelen, 0);
if (res == SOCKET_ERROR)
{
printf("Failed to send message. Error: %d\n", WSAGetLastError());
break;
}
message += res;
messagelen -= res;
}
while (messagelen > 0);
if (messagelen == 0)
printf("Message sent.\n");
//close the client socket
closesocket(new_socket);
}
while (true);
//close the server socket
closesocket(s);
WSACleanup();
return 0;
}
On the client side, the only real problem I see is your recv()
call has a potential buffer overflow waiting to happen, since you ask it to read 75 bytes, and that is the exact size of your buffer. 在客户端,我看到的唯一真正的问题是您的recv()
调用有潜在的缓冲区溢出等待发生,因为您要求它读取75个字节,这就是缓冲区的确切大小。 It just happens that your server is only sending 74 bytes max, but if it ever sent more, you could overflow the buffer when appending the '\\0'
terminator to it. 碰巧您的服务器最多仅发送74个字节,但是如果发送的字节数更多,则在将'\\0'
终止符附加到该缓冲区时,您可能会溢出缓冲区。
So, either: 因此,要么:
call recv()
with sizeof(server_reply)-1
as the buffer size, to give yourself room for the added terminator: 调用recv()
并将sizeof(server_reply)-1
作为缓冲区大小,以便为自己添加的终结符留出空间:
recv_size = recv(s, server_reply, sizeof(server_reply)-1, 0);
use printf()
instead of puts()
so you don't need to null-terminate the buffer at all when printing it to the console. 使用printf()
而不是puts()
因此在将其打印到控制台时根本不需要对缓冲区进行null终止。 You can pass recv_size
as a parameter to limit the amount of text being printed: 您可以传递recv_size
作为参数来限制要打印的文本量:
//server_reply[recv_size] = '\\0'; //puts(server_reply); printf("%.*s", recv_size, server_reply);
From the MSDN documentation on closesocket(): 从closesocket()的MSDN文档中:
Note To assure that all data is sent and received on a connection, an application should call shutdown before calling closesocket (see Graceful shutdown, linger options, and socket closure for more information). 注意:为确保所有数据都是通过连接发送和接收的,应用程序应在调用closesocket之前先调用shutdown(有关更多信息,请参见正常关闭,延迟选项和套接字关闭)。 Also note, an FD_CLOSE network event is not posted after closesocket is called. 另请注意,调用closesocket后不会发布FD_CLOSE网络事件。
Basically the data you have sent was still pending when you closed the socket. 基本上,关闭套接字后,已发送的数据仍处于待处理状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.