David F. Marker <interprotech@ameritech.net> wrote:
Have a TCP/IP server that manages up to 32 (1 listen + 31 potential
clients)descriptors underneath a QNX4 select Receive(). When the peer drops
their application the descriptor becomes ready and read for zero bytes–a
typical disconnection. However, if the peer does not properly shutdown the
socket (i.e. peer cold boot) I never get any notification that the they have
disconnected. Netstat show connection as still being established. I have
tried enabling SO_KEEPALIVE whereby keepalive probes are sent but I still am
not getting desired results. Any suggestions?
Are you sure the keepalive probe is send out? Be default, it will
only send out after 2 hours idle. You need TCP_KEEPALIVE to change
that 2 hours. Also, it take about 10min to probe and decided to
drop the link.
Below is a little small program I used to test these things.
-xtang
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <unistd.h>
#include <netdb.h>
#include <errno.h>
#ifndef TCP_KEEPALIVE /* should be defined in netinet/tcp.h */
#define TCP_KEEPALIVE 0x04
#endif
main(int argc, char ** argv)
{
int skeepalive = 60;
int gkeepalive;
int len = sizeof(gkeepalive);
int sock;
struct sockaddr_in server;
struct hostent *hp;
struct protoent *proto;
if (argc < 4) {
fprintf(stderr, “Usage: %s \n”, argv[0]);
exit(-1);
}
skeepalive = atoi(argv[3]);
if ((hp = gethostbyname(argv[1])) == 0) {
fprintf(stderr, “Wrong host!\n”);
exit(-1);
}
memcpy(&server.sin_addr, hp->h_addr, hp->h_length);
server.sin_port = htons(atoi(argv[2]));
server.sin_family = AF_INET;
if ((proto = getprotobyname(“TCP”)) == NULL) {
perror (“getprotobyname”);
exit (-1);
}
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror(“socket”);
exit(-1);
}
if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &skeepalive, sizeof(int)) == -1) {
perror(“setsockopt(SO_KEEPALIVE)”);
exit(-1);
}
if (getsockopt(sock, proto->p_proto, TCP_KEEPALIVE, &gkeepalive, &len) == -1)
printf(“getsockopt() before connect failed. errno = %d\n”, errno);
else
printf(“getsockopt() before connect success. Idle time = %d\n”, gkeepalive);
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror(“connect”);
exit(-1);
}
if (getsockopt(sock, proto->p_proto, TCP_KEEPALIVE, &gkeepalive, &len) == -1)
printf(“getsockopt() after connect is failed. errno = %d\n”, errno);
else
printf(“getsockopt() after connect is successed. Idle time = %d\n”, gkeepalive);
if (setsockopt(sock, proto->p_proto, TCP_KEEPALIVE, &skeepalive, len) == -1)
{
perror(“setsockopt()”);
exit(-1);
}
printf(“setsockopt is successed\n”);
if (getsockopt(sock, proto->p_proto, TCP_KEEPALIVE, &gkeepalive, &len) == -1)
{
perror(“getsockopt()”);
exit (-1);
}
printf(“getsockopt() now got idle time = %d\n”, gkeepalive);
printf("\nWaiting…, press a key to continue\n");
gkeepalive = getch();
close(sock);
}