TCP套接字recv,指示“;“意外”;成功发送后断开连接
我有一个处于阻塞模式的TCP套接字,用于请求/响应协议的客户端。有时我发现,如果某个套接字未使用一两分钟,则TCP套接字recv,指示“;“意外”;成功发送后断开连接,c,sockets,tcp,C,Sockets,Tcp,我有一个处于阻塞模式的TCP套接字,用于请求/响应协议的客户端。有时我发现,如果某个套接字未使用一两分钟,则send调用将成功并指示已发送的所有字节,但下面的recv返回零,表示已关闭。我在Windows和Linux客户机上都看到了这一点 服务器人员告诉我,如果他们已经收到数据,他们总是在关机前发送一些响应,但是如果服务器资源不足,他们可能会关闭一个尚未收到任何数据的套接字 我看到的情况是否表明服务器在我不使用连接时关闭了连接,那么为什么发送然后成功 在这种情况下,自动检测请求的正确方法是什么,
send
调用将成功并指示已发送的所有字节,但下面的recv
返回零,表示已关闭。我在Windows和Linux客户机上都看到了这一点
服务器人员告诉我,如果他们已经收到数据,他们总是在关机前发送一些响应,但是如果服务器资源不足,他们可能会关闭一个尚未收到任何数据的套接字
我看到的情况是否表明服务器在我不使用连接时关闭了连接,那么为什么发送然后成功
在这种情况下,自动检测请求的正确方法是什么,以便在新连接上重新发送请求,但请记住,如果服务器实际收到某些请求两次,可能会产生意外影响
//not full code (buffer management, wrapper functions, etc...)
//no special flags/options are being set, just socket then connect
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(sock, addr, addrlen);
//some time later after many requests/responses, normally if was inactive for a minute
//sending about 50 bytes for requests, never actually seen it loop, or return 0
while (more_to_send) check(send(sock, buffer, len, 0));
//the very first recv returns 0, never seen it happen part way through a response (few KB to a couple of MB)
while (response_not_complete) check(recv(sock, buffer, 4096, 0));
- 如果您没有从服务器获得请求的应用程序确认,请重新发送它
- 将您的事务设计为这样,以便重新发送它们不会造成不良影响
- 如果您没有从服务器获得请求的应用程序确认,请重新发送它
- 将您的事务设计为这样,以便重新发送它们不会造成不良影响
我看到的情况是否表明服务器已关闭
连接,而我不使用它
对
,那么为什么send会成功呢
send()的成功告诉您,传入send()的部分(或全部)数据已成功复制到内核内缓冲区,并且从现在起,操作系统负责尝试将这些字节传递给远程对等方
特别是,它并不表示这些字节实际上已经通过网络(尚未)或已被服务器成功接收
自动检测此情况的正确方法是什么
在本例中,请求在新连接上重新发送,但与
请注意,如果服务器实际收到一些请求两次,则
会产生意想不到的影响吗
//not full code (buffer management, wrapper functions, etc...)
//no special flags/options are being set, just socket then connect
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(sock, addr, addrlen);
//some time later after many requests/responses, normally if was inactive for a minute
//sending about 50 bytes for requests, never actually seen it loop, or return 0
while (more_to_send) check(send(sock, buffer, len, 0));
//the very first recv returns 0, never seen it happen part way through a response (few KB to a couple of MB)
while (response_not_complete) check(recv(sock, buffer, 4096, 0));
正如EJP所建议的,最好的方法是设计通信协议,使发送同一请求两次与发送一次没有不同的效果。一种方法是为您发送的每条消息添加一个唯一的ID,并向服务器添加一些逻辑,这样,如果服务器接收到一条ID与它已经处理的ID相同的消息,它会将该消息作为副本丢弃
让服务器向每条消息发回一个明确的响应(这样您就可以确定您的消息是否已通过并已被处理)可能会有所帮助,但当然,您必须开始担心这样的情况:您的消息已被接收和处理,但TCP连接在响应返回给您之前中断,等等
您可以做的另一件事(如果您还没有这样做)是监视TCP套接字的状态(通过select()、poll()或类似方式),以便在远程对等方关闭其套接字末端时立即通知您的程序(通过套接字select()-ing将其设置为ready for read)。这样,您就可以在尝试发送()命令之前很好地处理关闭的TCP连接,而不仅仅是在之后才了解它,而且这应该是一个不太难处理的情况,因为在这种情况下,不存在命令是否“通过”的问题
我看到的情况是否表明服务器已关闭
连接,而我不使用它
对
,那么为什么send会成功呢
send()的成功告诉您,传入send()的部分(或全部)数据已成功复制到内核内缓冲区,并且从现在起,操作系统负责尝试将这些字节传递给远程对等方
特别是,它并不表示这些字节实际上已经通过网络(尚未)或已被服务器成功接收
自动检测此情况的正确方法是什么
在本例中,请求在新连接上重新发送,但与
请注意,如果服务器实际收到一些请求两次,则
会产生意想不到的影响吗
//not full code (buffer management, wrapper functions, etc...)
//no special flags/options are being set, just socket then connect
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connect(sock, addr, addrlen);
//some time later after many requests/responses, normally if was inactive for a minute
//sending about 50 bytes for requests, never actually seen it loop, or return 0
while (more_to_send) check(send(sock, buffer, len, 0));
//the very first recv returns 0, never seen it happen part way through a response (few KB to a couple of MB)
while (response_not_complete) check(recv(sock, buffer, 4096, 0));
正如EJP所建议的,最好的方法是设计通信协议,使发送同一请求两次与发送一次没有不同的效果。一种方法是为您发送的每条消息添加一个唯一的ID,并向服务器添加一些逻辑,这样,如果服务器接收到一条ID与它已经处理的ID相同的消息,它会将该消息作为副本丢弃
让服务器向每条消息发回一个明确的响应(这样您就可以确定您的消息是否已通过并已被处理)可能会有所帮助,但当然,您必须开始担心这样的情况:您的消息已被接收和处理,但TCP连接在响应返回给您之前中断,等等
您可以做的另一件事(如果您还没有这样做)是监视TCP套接字的状态(通过select()、poll()或类似方式),以便在远程对等方关闭其套接字末端时立即通知您的程序(通过套接字select()-ing将其设置为ready for read)。这样,您就可以在尝试发送()命令之前很好地处理关闭的TCP连接,而不仅仅是在之后才了解它,而且这应该是一个不太难处理的情况,因为在这种情况下,不存在命令是否“通过”的问题。send
使用第四个参数,flags
,您没有指定的。如果是这样,标志将是随机的,它们可能会影响传输。同样,对于recv
My bad it