TCP aborted from state FIN_WAIT1 after empty 60 secs

Rory Byrne rory at nybek.com
Sat Mar 7 16:24:31 UTC 2015


On Sat, Mar 07, 2015 at 03:49:02PM +0000, Rory Byrne wrote:
> 
> See attached for test code and a tcpdump trace. The client and server must be
> on different hosts: the TCP connection won't be aborted if you run it over lo0.

Sorry, the test code got dropped. I'll include it inline.

---
 client.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 server.c |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 191 insertions(+)
 create mode 100644 client.c
 create mode 100644 server.c

diff --git a/client.c b/client.c
new file mode 100644
index 0000000..e908289
--- /dev/null
+++ b/client.c
@@ -0,0 +1,90 @@
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#define PORT 7777
+#define RCVBUF_SIZE 8192
+#define READ_SIZE 512
+
+void die(const char *where)
+{
+    perror(where);
+    exit(EXIT_FAILURE);
+}
+
+void usage_exit(const char *prog_name, const char *err_msg)
+{
+    if (err_msg != NULL)
+        fprintf(stderr, "%s\n", err_msg);
+    fprintf(stderr, 
+            "usage: %s ip-address\n"
+            "    -h      Print usage and exit.\n",
+            prog_name);
+    exit(EXIT_FAILURE);
+}
+
+void set_socket_options(int fd)
+{
+    int r, val;
+
+    val = RCVBUF_SIZE,
+    r = setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val));
+    if (r == -1) 
+        die("setting SO_RCVBUF");
+}
+
+int main(int argc, char *argv[])
+{
+    int sockfd, total, n, r;
+    char buf[READ_SIZE];
+    struct sockaddr_in servaddr;
+
+    if (argc != 2 || strcmp("-h", argv[1]) == 0)
+        usage_exit(argv[0], NULL);
+
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_port = htons(PORT);
+
+    r = inet_pton(AF_INET, argv[1], &servaddr.sin_addr.s_addr);
+    if (r != 1) {
+        fprintf(stderr, "failed at inet_pton()\n");
+        exit(EXIT_FAILURE);
+    }
+    
+    sockfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (sockfd == -1) 
+        die("socket()");
+    
+    set_socket_options(sockfd);
+
+    r = connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
+    if (r == -1)
+        die("connect()");
+
+    /* Prompt user before reading next 512 byte block */
+    total = 0;
+    while ((n = read(sockfd, buf, READ_SIZE)) != 0) {
+        if (n == -1)
+            die("socket read()");
+        total += n;
+        printf("RECV: %d (%d)\n", n, total);
+
+        printf("Press RETURN to read next %d bytes: ", READ_SIZE);
+        while (getchar() != '\n')
+            ;
+    }
+    puts("End of input stream");
+    
+    close(sockfd);
+    puts("Connection closed");
+
+    exit(EXIT_SUCCESS);
+}
diff --git a/server.c b/server.c
new file mode 100644
index 0000000..ffdee85
--- /dev/null
+++ b/server.c
@@ -0,0 +1,101 @@
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#define PORT 7777
+#define SNDBUF_SIZE (50 * 1024)
+#define PAYLOAD_SIZE (20 * 1024)
+#define BACKLOG 128
+
+void die(const char *where)
+{
+    perror(where);
+    exit(EXIT_FAILURE);
+}
+
+void get_payload(char *buf, int size)
+{
+    int i;
+
+    for (i = 0; i < size; i++) {
+        buf[i] = '.';
+    }
+}
+
+void set_socket_options(int fd)
+{
+    int r, val;
+
+    val = 1;
+    r = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
+    if (r == -1) 
+        die("setting SO_REUSEADDR");
+
+    val = SNDBUF_SIZE,
+    r = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
+    if (r == -1) 
+        die("setting SO_SNDBUF");
+}
+
+int main(void)
+{
+    int listenfd, connfd, r;
+    ssize_t n;
+    struct sockaddr_in servaddr;
+    char buf[PAYLOAD_SIZE];
+
+    memset(buf, 0, sizeof(buf));
+    get_payload(buf, sizeof(buf));
+
+    listenfd = socket(AF_INET, SOCK_STREAM, 0);
+    if (listenfd == -1)
+        die("socket");
+
+    set_socket_options(listenfd);
+
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+    servaddr.sin_port = htons(PORT);
+
+    r = bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
+    if (r == -1)
+        die("bind()");
+
+    r = listen(listenfd, BACKLOG);
+    if (r == -1)
+        die("listen()");
+
+    puts("-- waiting for client connection");
+    connfd = accept(listenfd, (struct sockaddr *) NULL, NULL);
+    if (connfd == -1)
+        die("accept()");
+    puts("-- client connected");
+
+    puts("-- closing listening socket");
+    r = close(listenfd);
+    if (r == -1)
+        die("closing listenfd");
+
+    puts("-- writing payload");
+    n = write(connfd, buf, sizeof(buf));
+    if (n == -1) {
+        die("write()");
+    } else if (n != sizeof(buf)) {
+        fprintf(stderr, "failed to write full buffer");
+        exit(EXIT_FAILURE);
+    }
+
+    puts("-- closing connected socket");
+    r = close(connfd);
+    if (r == -1) 
+        die("closing connfd");
+
+    exit(EXIT_SUCCESS);
+}
-- 
1.7.10.4



More information about the freebsd-questions mailing list