在服务器死后,TCP是否保持活动(有少量超时),以防止客户端挂在recv上?
设想情况:
服务器和客户端在单独的机器上运行:
在客户端睡眠期间,服务器被插入,现在:
设置KEEPALIVE选项:
void TCPclient::setkeepalive()
{
int optval;
socklen_t optlen = sizeof(optval);
/* Check the status for the keepalive option */
if(getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {
throw std::string("getsockopt");
}
optval = 1;
optlen = sizeof(optval);
if(setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
close(s);
exit(EXIT_FAILURE);
}
optval = 2;
if (setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &optval, optlen) < 0) {
throw std::string("setsockopt");
}
optval = 15;
if (setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) {
throw std::string("setsockopt");
}
optval = 15;
if (setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) {
throw std::string("setsockopt");
}
}Linux3.2.084-通用
发布于 2015-06-26 15:57:47
当线路闲置15秒时,保持活动状态。在您的示例中,Keepalive启动超时为15秒,睡眠为10秒,这意味着"Hello server“将是服务器被杀死后发送的下一个命令。
您的Linux将尝试多次重传此消息。保护仍然不会被触发。到达重试限制后,连接将中断--这将需要10-30分钟。
发布于 2015-06-29 05:38:57
@MMA的回答是正确的。我写了一个类似的客户在写之前等了20秒。一旦客户端唤醒并发送消息,由“保持活动”发送的ACK消息将不再发送(连接不再空闲)。
在15次重试(在/proc/sys/net/ipv4 4中配置了tcp_retries2 )之后,发送tcp段,其中超时呈指数增长,直到达到2分钟(在我的例子中),连接被设置为错误,并使用ETIMEDOUT (errno 110)挂起读取或recv返回。在我看来,大约花了15分钟。这一次取决于RTO。查看TCPDUMP,有两个ack在三路握手之后(我不知道为什么第一个是2ack),然后是15条带有数据和推送标志集的消息。
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on p2p1, link-type EN10MB (Ethernet), capture size 65535 bytes
01:16:45.296179 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [S], seq 515423022, win 14600, options [mss 1460,sackOK,TS val 19212623 ecr 0,nop,wscale 7], length 0
E..<.a@.@......d4.....'...........9............
.%)O........
01:16:45.477983 IP ec2-52-7-150-140.compute-1.amazonaws.com.10221 > 192.168.2.100.60895: Flags [S.], seq 3672727778, ack 515423023, win 26847, options [mss 1436,sackOK,TS val 114765522 ecr 19212623,nop,wscale 7], length 0
E..<..@.-...4......d'.....`..../..h............
.....%)O....
01:16:45.478046 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [.], ack 1, win 115, options [nop,nop,TS val 19212805 ecr 114765522], length 0
E..4.b@.@......d4.....'..../..`....s.......
.%*.....
01:17:00.512812 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [.], ack 1, win 115, options [nop,nop,TS val 19227840 ecr 114765522], length 0
E..4.c@.@......d4.....'.......`....s.......
.%d.....
01:17:00.731160 IP ec2-52-7-150-140.compute-1.amazonaws.com.10221 > 192.168.2.100.60895: Flags [.], ack 1, win 210, options [nop,nop,TS val 114769336 ecr 19212805], length 0
E..4N.@.-.r.4......d'.....`..../....M......
..=..%*.
01:17:05.478933 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19232806 ecr 114769336], length 14
E..B.d@.@......d4.....'..../..`....s.......
.%x&..=.Hello Word :).
01:17:06.027768 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19233354 ecr 114769336], length 14
E..B.e@.@......d4.....'..../..`....s.......
.%zJ..=.Hello Word :).
01:17:07.120879 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19234448 ecr 114769336], length 14
E..B.f@.@......d4.....'..../..`....s.......
.%~...=.Hello Word :).
01:17:09.312833 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19236640 ecr 114769336], length 14
E..B.g@.@......d4.....'..../..`....s.......
.%. ..=.Hello Word :).
01:17:13.697663 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19241024 ecr 114769336], length 14
E..B.h@.@......d4.....'..../..`....s.......
.%.@..=.Hello Word :).
01:17:22.466187 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19249793 ecr 114769336], length 14
E..B.i@.@......d4.....'..../..`....s.......
.%....=.Hello Word :).
01:17:40.001653 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19267328 ecr 114769336], length 14
E..B.j@.@......d4.....'..../..`....s.......
.%....=.Hello Word :).
01:18:15.074493 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19302401 ecr 114769336], length 14
E..B.k@.@......d4.....'..../..`....s.......
.&....=.Hello Word :).
01:19:25.217799 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19372545 ecr 114769336], length 14
E..B.l@.@......d4.....'..../..`....s.......
.'....=.Hello Word :).
01:21:25.537775 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 19492864 ecr 114769336], length 14
E..B.m@.@......d4.....'..../..`....s.......
.)p...=.Hello Word :).
01:23:25.856854 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, 69336], length 14
E..B.n@.@......d4.....'..../..`....s.......
.+F...=.Hello Word :).
01:25:26.176894 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, 69336], length 14
E..B.o@.@......d4.....'..../..`....s.......
.-....=.Hello Word :).
01:27:26.497691 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, 69336], length 14
E..B.p@.@......d4.....'..../..`....s.......
......=.Hello Word :).
01:29:26.816905 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, 69336], length 14
E..B.q@.@......d4.....'..../..`....s.......
.0....=.Hello Word :).
01:31:27.137013 IP 192.168.2.100.60895 > ec2-52-7-150-140.compute-1.amazonaws.com.10221: Flags [P.], seq 1:15, ack 1, win 115, options [nop,nop,TS val 20094464 ecr 114769336], length 14
E..B.r@.@......d4.....'..../..`....s.......
.2....=.Hello Word :).我使用的客户端代码:
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/tcp.h>
#define DEST_PORT 10221
#define ADDRLEN INET_ADDRSTRLEN
int main(int argc, char** argv)
{
int sock;
int bytesWritten;
struct sockaddr_in their_addr;
char buffer[] = "Hello Word :)";
char addrstr[ADDRLEN + 1];
if (argc != 2)
{
printf("ERROR - Number of args\n");
return 10;
}
strncpy(addrstr, argv[1], ADDRLEN);
bzero(&their_addr, sizeof(their_addr));
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(DEST_PORT);
if (inet_pton(AF_INET, addrstr,(void *)&their_addr.sin_addr) != 1)
{
printf("ERROR - Converting Address: %d\n", errno);
return 2;
}
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
printf("ERROR - Socket could not be open: %d\n", errno);
return 1;
}
//// Copied option setting
int optval;
socklen_t optlen = sizeof(optval);
/* Check the status for the keepalive option */
if(getsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, &optlen) < 0) {
printf("ERROR - SOL_SOCKET: %d\n", errno);
return 19;
}
optval = 1;
optlen = sizeof(optval);
if(setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
printf("ERROR - SOL_SOCKET-2: %d\n", errno);
return 20;
}
optval = 2;
if (setsockopt(sock, SOL_TCP, TCP_KEEPCNT, &optval, optlen) < 0) {
printf("ERROR - SOL_TCP: %d\n", errno);
return 21;
}
optval = 15;
if (setsockopt(sock, SOL_TCP, TCP_KEEPIDLE, &optval, optlen) < 0) {
printf("ERROR - SOL_TCP-2: %d\n", errno);
return 22;
}
optval = 15;
if (setsockopt(sock, SOL_TCP, TCP_KEEPINTVL, &optval, optlen) < 0) {
printf("ERROR - SOL_TCP-3: %d\n", errno);
return 23;
}
/////
if (connect(sock, (const struct sockaddr *)&their_addr,
(socklen_t)sizeof(their_addr)) == -1)
{
printf("ERROR - Could not connect to destination: %d\n", errno);
return 3;
}
/// Sleep 20 seconds
sleep(20);
printf("About to write\n");
if ((bytesWritten = write(sock, (const void *)buffer, sizeof(buffer))) == -1)
{
printf("ERROR - Sending message: %d\n", errno);
return 4;
}
printf("Message Sent to Address %s, Port: %d\n\n", addrstr, DEST_PORT);
int bytesRead;
if ((bytesRead = read(sock, buffer, sizeof(buffer))) == -1)
{
printf("ERROR - Sending message: %d\n", errno);
return 4;
}
close(sock);
return 0;
}我在AWS中托管的服务器上运行这个测试。模拟删除服务器而没有注意到客户端的方法是:我有一个与服务器相关联的公共(弹性) IP,在三次握手之后,我立即将Elastic从服务器上断开。我不能粘贴服务器代码,但在这里不相关。
请不要因为发送消息而停止在本例中保持活动。
https://stackoverflow.com/questions/31076858
复制相似问题