Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <netinet/ip.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <pthread.h>
- static void * server(void*);
- static void * connecter(void*);
- static int s_clt;
- static struct sockaddr_in a_srv;
- static struct sockaddr_in a_clt;
- static int is_client;
- static void wait_for_close(int);
- static void close_on_read(int);
- int main(int argc, char ** argv) {
- int port;
- int aux;
- socklen_t slen;
- pthread_t bux;
- int s_srv = socket(PF_INET,SOCK_STREAM,0);
- if (s_srv<1) { perror("server socket"); return 1; }
- if (argc < 3) {
- fprintf(stderr, "Use: %s <port> {c|s}\n", argv[0]);
- return 1;
- }
- port = atoi(argv[1]);
- if (port <= 0) {
- fprintf(stderr, "port?\n"); return 1;
- }
- if (argv[2][0] == 'c') {
- is_client = 1;
- fprintf(stdout, "Will initiate client close\n");
- } else {
- is_client = 0;
- fprintf(stdout, "Will initiate server close\n");
- }
- a_srv.sin_family = a_clt.sin_family = AF_INET;
- a_srv.sin_port = htons(port);
- a_clt.sin_port = htons(port+1);
- a_srv.sin_addr.s_addr = a_clt.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- if (bind(s_srv, (struct sockaddr*)&a_srv, sizeof(struct sockaddr_in))) {
- perror("binding server"); return 1;
- }
- if (listen(s_srv, 5)) { perror("listen"); return 1; }
- pthread_create(&bux, 0, connecter, 0);
- while (1) {
- struct sockaddr_in a_inp;
- aux = accept(s_srv, (struct sockaddr*)&a_inp, &slen);
- int * fd = malloc(sizeof(int));
- *fd = aux;
- pthread_create(&bux, 0, server, fd);
- }
- }
- void * connecter(void * arg) {
- int i = 20;
- int yes = 1;
- while (i--) {
- s_clt = socket(PF_INET,SOCK_STREAM,0);
- if (s_clt<1) { perror("server socket"); _exit(1); }
- if (setsockopt(s_clt, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
- perror("setsockopt"); _exit(1);
- }
- if (bind(s_clt, (struct sockaddr*)&a_clt, sizeof(struct sockaddr_in))) {
- perror("binding client"); _exit(1);
- }
- fprintf(stdout, "connecting...\n");
- if (connect(s_clt, (struct sockaddr*)&a_srv, sizeof(struct sockaddr_in))) {
- perror("connect");
- _exit(1);
- }
- if (is_client) {
- close_on_read(s_clt);
- } else {
- wait_for_close(s_clt);
- }
- }
- return 0;
- }
- void * server(void * arg) {
- int fd = *(int*)arg;
- free(arg);
- if (is_client) {
- wait_for_close(fd);
- } else {
- close_on_read(fd);
- }
- return 0;
- }
- void close_on_read(int fd) {
- unsigned char c;
- fprintf(stdout, "Reading child connection\n");
- int rc = read(fd, &c, 1);
- if (rc < 0) {
- perror("read"); _exit(1);
- }
- if (!rc) {
- fprintf(stderr, "unexpected EOF?\n"); _exit(1);
- }
- fprintf(stdout, "byte sent, closing\n");
- shutdown(fd, SHUT_RDWR);
- close(fd);
- }
- void wait_for_close(int fd) {
- unsigned char c;
- int rc = write(fd, &c, 1);
- if (rc < 0) {
- perror("write"); _exit(1);
- }
- // read should exit with EOF
- rc = read(fd, &c, 1);
- if (rc < 0) {
- perror("read"); _exit(1);
- }
- if (rc > 0) {
- fprintf(stderr, "what read?\n"); _exit(1);
- }
- fprintf(stdout, "Received EOF\n");
- shutdown(fd, SHUT_RDWR);
- close(fd);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement