/* tcpblockio.c - a set of routines to make TCP easier to use */ #include #include #include #include #include #include #include #include #include #include "tcpblockio.h" #define MAXHOSTNAMELEN 256 int writeblock( int fd, char *buffer, int nbytes ) { int n; /* number of bytes actually sent in one write */ int offset; /* total number of bytes sent so far */ for( offset = 0; offset < nbytes; offset += n ) { if( (n = send(fd, &buffer[offset], nbytes-offset, 0)) < 0 ) { if( errno == EINTR ) n = 0; /* interrupted by a signal, keep going */ else { perror("send to socket"); return -1; } } } return offset; /* return total number of bytes actually sent */ } int readblock( int fd, char *buffer, int nbytes ) { int n; /* number of bytes actually received in one read */ int offset; /* total number of bytes received so far */ for( offset = 0; offset < nbytes; offset += n ) { if( (n = recv(fd, &buffer[offset], nbytes-offset, 0)) < 0 ) { if( errno == EINTR ) n = 0; /* interrupted by a signal, keep going */ else { perror("recv from socket"); return -1; } } else if( n == 0 ) break; /* end of file on receive */ } return offset; /* return total number of bytes actually read */ } /* Opens a new TCP socket to the server on node server_node, port server_port. Returns in server_addr the server's internet address structure, and in client_addr the client's internet address structure. */ int openclient( int server_port, char *server_node, struct sockaddr_in *server_addr, struct sockaddr_in *client_addr ) { int length, fd; struct sockaddr_in address1, address2; struct hostent *node_ptr; char local_node[MAXHOSTNAMELEN]; /* get the internet name of the local host node on which we are running */ if( gethostname(local_node, MAXHOSTNAMELEN) < 0 ) { perror("openclient gethostname"); exit(EXIT_FAILURE); } /* set up the name of the remote host node for the server */ if( server_node == NULL ) server_node = local_node; /* default to local node */ /* get structure for remote host node on which server resides */ if( (node_ptr = gethostbyname(server_node)) == NULL ) { herror(server_node); exit(EXIT_FAILURE); } /* set up Internet address structure for the server */ if( server_addr == NULL ) server_addr = &address1; memset(server_addr, 0, sizeof(struct sockaddr_in)); server_addr->sin_family = node_ptr->h_addrtype; /* should be AF_INET */ server_addr->sin_port = htons(server_port); memcpy(&server_addr->sin_addr, node_ptr->h_addr, node_ptr->h_length); /* open an internet tcp socket */ if( (fd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) { perror("openclient socket"); exit(EXIT_FAILURE); } /* connect this socket to the server's Internet address */ if(connect(fd,(struct sockaddr *)server_addr,sizeof(struct sockaddr_in))<0) { perror("openclient connect"); exit(EXIT_FAILURE); } /* now find out what local port number was assigned to this client */ length = sizeof(struct sockaddr_in); if( client_addr == NULL ) client_addr = &address2; if( getsockname(fd, (struct sockaddr *)client_addr, &length) < 0 ) { perror("client getsockname"); exit(EXIT_FAILURE); } /* we are now successfully connected to a remote server */ return fd; } #define listening_depth 2 /* Opens a new TCP socket for the server at interface server_name, port server_port. Returns in server_addr the server's internet address structure. The server is NOT connected to a client on return. */ int openserver( int server_port, char *server_name, struct sockaddr_in *server_addr ) { int len; int fd; struct sockaddr_in address1; struct hostent *node_ptr; char local_node[MAXHOSTNAMELEN]; char *host_name; /* get the internet name of the local host node on which we are running */ if( gethostname(local_node, MAXHOSTNAMELEN) < 0 ) { perror("openserver gethostname"); exit(EXIT_FAILURE); } if( server_name == NULL ) host_name = local_node; /* default to local node */ else host_name = server_name; /* get structure for local interface server is to use */ if( (node_ptr = gethostbyname(host_name)) == NULL ) { herror(host_name); exit(EXIT_FAILURE); } /* set up Internet address structure for the server */ if( server_addr == NULL ) server_addr = &address1; memset(server_addr, 0, sizeof(struct sockaddr_in)); server_addr->sin_family = node_ptr->h_addrtype; /* should be AF_INET */ server_addr->sin_port = htons(server_port); if( server_name == NULL ) server_addr->sin_addr.s_addr=htonl(INADDR_ANY); /* use any interface */ else memcpy(&server_addr->sin_addr, node_ptr->h_addr, node_ptr->h_length); /* open an internet tcp socket */ if( (fd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ) { perror("openserver socket"); exit(EXIT_FAILURE); } /* bind this socket to the server's Internet address */ if( bind(fd,(struct sockaddr *)server_addr,sizeof(struct sockaddr_in))<0 ) { perror("openserver bind"); exit(EXIT_FAILURE); } /* now find out what local port number was assigned to this server */ len = sizeof(struct sockaddr); if( getsockname(fd, (struct sockaddr *)server_addr, &len) < 0 ) { perror("openserver getsockname"); exit(EXIT_FAILURE); } /* set up listening backlog for connect requests from clients */ if( listen(fd, listening_depth) < 0 ) { perror("openserver listen"); exit(EXIT_FAILURE); } /* we are now successfully established as a server */ fprintf(stderr, "server: at port %d on node %s, internet address %s\n", ntohs(server_addr->sin_port), host_name, inet_ntoa(server_addr->sin_addr)); return fd; }