[1566] in linux-net channel archive
TCP flakey - connection reset by peer [+test code]
daemon@ATHENA.MIT.EDU (Miquel van Smoorenburg)
Sun Dec 31 16:46:19 1995
To: submit-linux-dev-net@ratatosk.yggdrasil.com
From: miquels@drinkel.ow.org (Miquel van Smoorenburg)
Date: Sun, 31 Dec 1995 19:35:34 +0100 (MET)
Hello,
recently we have been experiencing spontaneous "connection
reset by peer" problems on our Linux server. People lose their
POP3 connections, proxy HTTP connections get closed in the
middle of a transfer, etc.
This happens on both 1.2.13 and 1.3.49,50,51.
Fortunately, I can now reproduce this problem. Compile the
example program below and execute the following in 5
virtual consoles (my system name is "drinkel", replace with yours)
2: ./problem2 -p 4001
3: ./problem2 -h drinkel -p 4001 -d 200
4: ./problem2 -h drinkel -p 4001 -c
5: ./problem2 -h drinkel -p 4001 -c
6: ./problem2 -h drinkel -p 4001
This starts a server(2), 2 processes that open and close connections
to the server in quick succession(4,5) and 2 processes that read
data from the server at different speeds. One of the two reading
processes(3,6) will die with "read: connection reset by peer".
This may take a while, ofcourse.
Test program:
------------------------- problem2.c--------------------------
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <getopt.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
/* Fill out a sockaddr_in struct. */
int getaddr(char *host, int port, struct sockaddr_in *sin)
{
struct hostent *h;
if ((h = gethostbyname(host)) == NULL) {
herror(host);
return -1;
}
memset(sin, 0, sizeof(struct sockaddr_in));
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
sin->sin_addr.s_addr = *((long *)h->h_addr);
return 0;
}
/* Create a server. */
int server(int port)
{
struct sockaddr_in sin;
int s, n, len, i;
char buf[1024];
/* Fill the buffer. */
for(i = 0; i < 1023; i++) {
if (i && (i % 78) == 0)
buf[i] = '\n';
else
buf[i] = (i % 26) + 'A';
}
buf[i] = 0;
/* Prevent zombies. */
signal(SIGCHLD, SIG_IGN);
/* Create socket. */
if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket");
return -1;
}
/* Bind to any address. */
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
sin.sin_addr.s_addr = INADDR_ANY;
if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("bind");
close(s);
return -1;
}
printf("Server start\n");
while(1) {
/* Wait for a connection. */
if (listen(s, 128) < 0) {
perror("listen");
close(s);
return -1;
}
/* Accept the connection. */
len = sizeof(sin);
if ((n = accept(s, (struct sockaddr *)&sin, &len)) < 0) {
perror("accept");
close(s);
return -1;
}
/* Fork a process. */
if (fork() == 0) {
close(s);
/* Keep on writing blocks of 1024 bytes as fast as we can. */
while(1) {
if (write(n, buf, 1024) < 0 && errno != EINTR)
break;
}
/*perror("write");*/
exit(0);
}
close(n);
}
/*NOTREACHED*/
return 0;
}
int main(int argc, char **argv)
{
int i, s;
int cnt = 0;
int delay = 0;
char buf[1024];
struct sockaddr_in sin;
char *host = NULL;
int port = 0;
int con = 0;
while((i = getopt(argc, argv, "h:p:d:c")) != EOF) {
switch(i) {
case 'h':
host = optarg;
break;
case 'p':
port = atoi(optarg);
break;
case 'd':
delay = atoi(optarg);
break;
case 'c':
con = 1;
break;
default:
fprintf(stderr, "Usage: %s -p port [-h host] [-d delay] [-c]\n", argv[0]);
exit(1);
}
}
if (port == 0) {
fprintf(stderr, "Usage: %s -p port [-h host] [-d delay]\n", argv[0]);
exit(1);
}
if (host == NULL) {
server(port);
exit(1);
}
while(1) {
/* Open client socket. */
if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket");
exit(1);
}
if (getaddr(host, port, &sin) < 0) {
exit(1);
}
/* Connect to server. */
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
perror("connect");
exit(1);
}
if (!con) while(1) {
if (read(s, buf, 1024) <= 0) {
perror("read");
exit(1);
}
buf[79] = 0;
printf("%02d - %s\n", cnt, buf);
fflush(stdout);
cnt = (cnt + 1) % 100;
if (delay) usleep(delay * 1000);
}
read(s, buf, 1024);
printf("Close\n");
close(s);
}
return(0);
}
------------------------- problem2.c--------------------------
Mike.
--
+ Miquel van Smoorenburg + Cistron Internet Services + Living is a |
| miquels@cistron.nl (SP5) | Independent Dutch ISP | horizontal |
+ miquels@drinkel.ow.org + http://www.cistron.nl/ + fall +