Here is my test code:
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
int set_keep_alive(int sockfd) {
int optval = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) == -1) {
perror("setsockopt");
close(sockfd);
return -1;
}
int flags = 6;
if (setsockopt(sockfd , IPPROTO_TCP, TCP_KEEPIDLE, (void *)&flags, sizeof(flags)))
{
return -1;
};
flags = 3;
if (setsockopt(sockfd , IPPROTO_TCP, TCP_KEEPINTVL, (void *)&flags, sizeof(flags)))
{
return -1;
};
flags = 3;
if (setsockopt(sockfd , IPPROTO_TCP, TCP_KEEPCNT, (void *)&flags, sizeof(flags)))
{
return -1;
};
return 0;
}
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "usage: %s <ip> <port>\n", argv[0]);
return -1;
}
char const *IP = argv[1];
int PORT = atoi(argv[2]);
int fd = socket(AF_INET, SOCK_STREAM, 0);
set_keep_alive(fd);
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
inet_pton(AF_INET, IP, &addr.sin_addr);
int ret;
ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
printf("connect failed, ret = %d, errno=%d\n", ret, errno);
perror("");
return 1;
}
for(int i = 0;;i++, sleep(1)) {
char buf[100];
sprintf(buf, "hello%d", i%10);
int ret = send(fd, buf, strlen(buf), MSG_CONFIRM);
printf("%d,write ret = %d\n", i, ret);
}
close(fd);
return 0;
}
Assume its called client.c
gcc client.c
gota.out
- In the server, use
nc -l -p <PORT>
./a.out <Server IP> <PORT>
: it will print
0,write ret = 6
1,write ret = 6
2,write ret = 6
3,write ret = 6
4,write ret = 6
5,write ret = 6
6,write ret = 6
....
- In the server, there is a shell script called port-close.sh which drops newly incoming packets to the port
#!/bin/sh
iptables -I INPUT -p tcp --dport $1 -j DROP
if I run ./port-close.sh <PORT>
, in the client, after I wait for 15 seconds (the keep-alive time), still print ret = 6
which means success.
Please note replace <PORT> and <Server IP> to your configuration