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