COMSUB(3) COMSUB(3) NAME comsub - s2 routines for network communications DESCRIPTION comsub.doc K.Furukawa, Oct.2.1992, Jun.10.1993, Aug.9.1994. @(#)comsubs2.doc v1.2.0 K.Furukawa, Oct.1992-Aug.1994 Files comsub.c, comsubt.c, comsubu.c and comsubs.c containes s2 xxx functions for network communications. These routines are based on recho programs (see ~furukawa/tcpip/recho.tar.Z or olive:~ftp/pub/unix/recho.tar.Z). This package is available at ~furukawa/tcpip/s2.tar.Z or olive.kek.jp:~ftp/pub/unix/s2.tar.Z. It supports TCP and UDP communication between client and server. On the TCP server side it supports both single and multiple thread. (It means that the server process can fork a child to handle each connection, in order to accept multiple connection at a time.) As the UDP server is connectionless, it receive a message and send a message back to the original client. On the UDP client side it supports both normal and broadcast communication. It also supports timeout handling for send and receive routines. The file comsub.c defines s2 open, s2 bopen, s2 scopen, s2 send, s2 receive and s2 bsend routines for clients. The file comsubt.c defines s2 tsend, s2 treceive, s2 tusend and s2 tureceive routines for timeout handling. The file comsubu.c defines s2 uopen and s2 scuopen routines for connectionless udp clients. And the file comsubs.c defines s2 sopen, s2 accept, s2 sclose, s2 ureceive, s2 usend, s2 upeername and s2 upeerport routines for servers. These routines run on DecStation/Ultrix, VAX/Ultrix, Sun/SunOS, Sony/News, NeXT, Hpux, NEC/SXA, SGI/Irix, IBM/AIX, Apple/AUX, LynxOS, Mitsubishi/Umx, VAX/VMS/Win, VAX/VMS/Multinet, VAX/VMS/UCX, OS9/68K, MSDOS/PCTCP and MacOS/MacTCP. On VMS, OS9 and MSDOS systems multiple thread tcp servers are not supported. On VMS broadcasting is not supported. BASIC USAGE: The basic usage for above four modes are shown below. TCP single thread client-server [scheme 1] [client side] [server side] sl = s2 sopen(ps,ss,"tcp",...); sd = s2 open(pc,sc,"tcp",...); loop: sd = s2 accept(sl,0,...); s2 send(sd,...); s2 receive(sd,...); s2 receive(sd,...); s2 send(sd,...); ... ... s2 close(sd); s2 sclose(sd); goto loop; TCP multiple thread client-server [scheme 2] [client side] [server side] sl = s2 sopen(ps,ss,"tcp",...); sd = s2 open(pc,sc,"tcp",...); loop: sd = s2 accept(sl,1,...); if (sd==0) goto loop; s2 send(sd,...); s2 receive(sd,...); s2 receive(sd,...); s2 send(sd,...); ... ... s2 close(sd); s2 sclose(sd); exit(); UDP client-server [scheme 3] [client side] [server side] sd = s2 sopen(ps,ss,"udp",...); sd = s2 open(pc,sc,"udp",...); s2 send(sd,...); loop: s2 ureceive(sd,...); s2 receive(sd,...); s2 usend(sd,...); ... ... s2 close(sd); goto loop; UDP broadcast client-server [scheme 4] [client side] [server side(s)] sd = s2 sopen(ps,ss,"udp",...); sd = s2 bopen(pc,sc,"udp",...); s2 bsend(sd,...); loop: s2 ureceive(sd,...); s2 tureceive(sd,...); s2 usend(sd,...); s2 tureceive(sd,...); s2 tureceive(sd,...); ... ... s2 close(sd); goto loop; EXAMPLE PROGRAMS: s2 recho and s2 rechod pair -- scheme 1, 2 or 3 (tcp or udp) s2 xfer and s2 xferd pair -- scheme 1, 3 or 4 (tcp or udp) s2 becho and s2 rechod pair -- scheme 4 (udp) s2 techo and s2 rechod pair -- scheme 1, 2 or 3 (tcp or udp) (timeout) s2 oecho and s2 rechod pair -- scheme 1, 2 or 3 (tcp or udp) (open/close socket for every message) s2 in2soc and s2 soc2out pair -- scheme 1 or 3 (tcp or udp) (connectionless) (separate package) BUGS: On VMS, OS9 and MSDOS systems multiple thread server is not supported. On VMS broadcasting is not supported. On OS9 s2 receive() (recv()) returns a error for the closed socket, while on unix it returns zero. (Maybe it's implementation difference.) REFERENCE MANUAL: Reference manual below is generated from source files with the command "comment comsub.c comsubs.c comsubt.c comsubu.c". /** * comsub -- communication subroutines * Kazuro Furukawa, KEK, Japan (furukawa@kek.jp) * (if you modified this code, please inform furukawa) * * K.Furukawa Nov.9.1988. (rwrite) * K.F Apr.13.1989. converted from rwrite (recho) * K.F Mar.19.1991. recho v3.4.2 * K.F Mar.24.1992.(2) comsub * K.F Sep.14.1992. add option 3 (bit 2) * Modifications * K.F Nov.26.1992. close failed socket correctly * K.F Mar.2.1993. move error code definition to comsub.h * K.F Jun.10.1993. add s2 bopen() for broadcasting * K.F Feb.21.1994. add s2 preopen() and s2 postopen * K.F Mar.3.1994. add s2 scopen() * * This module is a re-writing of zechosub. * This module defines basic rouines for socket communication. * int s2 open( portnum, service, protocol, hostname, option ) * int s2 scopen( destination, protocol, option ) * int s2 close( sd, option ) * int s2 send( sd, buffer, buflen, option ) * int s2 receive( sd, buffer, buflen, option ) * This module also defines rouines for broadcast communication. * int s2 bopen( portnum, service, protocol, hostname, option ) * int s2 bsend( sd, buffer, buflen, option ) * * If option is 1, error message is printed on to stderr * when error occured. * If option is 3, error and information message is printed on to stderr * when error occured. * Error code errno returned from the system subroutines are preserved * on return to the caller. * For usage, see comsubs2.doc or example programs such as * s2 recho, s2 becho, s2 oecho, s2 xfer, etc. */ char comsub what[] = "@(#)comsub.c v1.6.6 tcp|udp client subroutines, K.Furukawa, Aug.1994"; /* **/ /** * s2 open * s2 open prepares communication socket * * int s2 open( portnum, service, protocol, hostname, option ) * * if portnum is positive, it tries to open a socket to hostname * with the portnum and protocol, * then tries to open with service (service name or port number string) * then if portnum is negative, tries to open with -portnum * protocol is "tcp" or "udp" * hostname is a host name or ip address in dotted notation * if option is 1 or S2 OERR, error message is sent to stderr * if option is 3 or S2 OALL, error/info. message is sent to stderr * * return: positive/0 success, socket descriptor * -1 S2 NOSERV service not found * -2 S2 NOPORT no port/service specified * -3 S2 NOHOST unknown host * -4 S2 NOPROT protocol other than tcp/udp specified * -5 S2 OPENERR socket open failure * -6 S2 UBNDERR udp bind failure * -7 S2 CONNERR socket connect failure */ int s2 open( portnum, service, protocol, hostname, option ) int portnum; /* positive: port no, negative: default port */ char *service; /* service name, or null */ char *protocol; /* "tcp" or "udp" */ char *hostname; /* host name or ip-address */ int option; /* option 1: error, 2: info. message */ /* **/ /** * s2 bopen * s2 bopen prepares udp communication socket for broadcasting * * int s2 bopen( portnum, service, protocol, hostname, option ) * * if portnum is positive, it tries to open a socket to hostname * with the portnum * then tries to open with service (service name or port number string) * then if portnum is negative, tries to open with -portnum * only "udp" protocol is meaningful for broadcast * if option is 1 or S2 OERR, error message is sent to stderr * if option is 3 or S2 OALL, error/info. message is sent to stderr * if protocol is not "udp", S2 NOPROT is returned * * return: positive/0 success, socket descriptor * -1 S2 NOSERV service not found * -2 S2 NOPORT no port/service specified * -3 S2 NOHOST unknown host * -4 S2 NOPROT protocol other than udp specified * -5 S2 OPENERR socket open failure * -6 S2 UBNDERR udp bind failure/ broadcast assigning failure * -7 S2 CONNERR socket connect failure */ int s2 bopen( portnum, service, protocol, hostname, option ) int portnum; /* positive: port no, negative: default port */ char *service; /* service name, or null */ char *protocol; /* "udp" */ char *hostname; /* host name or ip-address */ int option; /* option 1: error, 2: info. message */ /* **/ /** * s2 scopen * s2 scopen prepares communication socket (sc open compatible) * * int s2 scopen( destination, protocol, option ) * * destination is a string, one of these forms * "service name", "port number", * "service name@host name", "port number@host name" * if option is 1 or S2 OERR, error message is sent to stderr * if option is 3 or S2 OALL, error/info. message is sent to stderr * * return: positive/0 success, socket descriptor * -1 S2 NOSERV service not found * -2 S2 NOPORT no port/service specified * -3 S2 NOHOST unknown host * -4 S2 NOPROT protocol other than tcp/udp specified * -5 S2 OPENERR socket open failure * -6 S2 UBNDERR udp bind failure * -7 S2 CONNERR socket connect failure */ int s2 scopen( destination, protocol, option ) char *destination; /* service and host */ char *protocol; /* "tcp" or "udp" */ int option; /* option 1: error, 2: info. message */ /* **/ /** * s2 close * s2 close close communication port * * int s2 close( sd, option ) * * return: always zero */ int s2 close( sd, option ) int sd; /* socket descriptor returned from s2 open */ int option; /* option 1/2: error/information message */ /* **/ /** * s2 send * s2 send sends message to communication port * calls send(2) system call. * * int s2 send( sd, buffer, buflen, option ) * * return: -21 S2 SENDERR send failure * positive byte count which has been sent */ int s2 send( sd, buffer, buflen, option ) int sd; /* socket descriptor returned from s2 open */ char *buffer; /* buffer to send */ int buflen; /* buffer length */ int option; /* option 1/2: error/information message */ /* **/ /** * s2 receive * s2 receive receives message from communication port * calls recv(2) system call. * * int s2 receive( sd, buffer, buflen, option ) * * return: -22 S2 RECVERR receive failure * positive byte count which has been received */ int s2 receive( sd, buffer, buflen, option ) int sd; /* socket descriptor returned from s2 open */ char *buffer; /* buffer to receive */ int buflen; /* buffer length */ int option; /* option 1: error/information message */ /* **/ /** * s2 bsend * s2 bsend sends message to broadcast address * calls sendto(2) system call. we need separate send routine * for bi-directional broadcast-and-reply communication * this routine should be used after s2 bopen * * int s2 bsend( sd, buffer, buflen, option ) * * return: -21 S2 SENDERR send failure * positive byte count which has been sent */ int s2 bsend( sd, buffer, buflen, option ) int sd; /* socket descriptor returned from s2 open */ char *buffer; /* buffer to send */ int buflen; /* buffer length */ int option; /* option 1/2: error/information message */ /* **/ /** * s2 currtime * returns string of current time * 23 characters like "day mmm dd hh:mm:ss.sss" */ char *s2 currtime() /* **/ /** * comsubs -- communication subroutines for server side * Kazuro Furukawa, KEK, Japan (furukawa@kek.jp) * (if you modified this code, please inform furukawa) * * K.Furukawa Nov.9.1988. (rwrited) * K.F Apr.13.1989. converted from rwrited (rechod) * K.F Jun.17.1992. rechod v3.4.2 * K.F Jul.20.1992.(x) comsubs * Modifications * K.F Sep.14.1992. add option 3 (bit 2) * K.F Oct.25.1992.(2) add reuseaddr in s2 sopen * K.F Nov.26.1992. close failed socket correctly * K.F Mar.2.1993. move error code definition to comsub.h * K.F Jun.15.1993. add s2 upeername * K.F Aug.9.1994. add s2 upeername * * This module is a re-writing of zechosub. * This module defines open(server), accept and close rouines * for socket communication at server side. * int s2 sopen( portnum, service, protocol, option ) * int s2 accept( sl, flag, option ) * int s2 sclose( sd, option ) * Routines s2 receive and s2 send in comsub.c will be used for * "tcp" data transfer. * For "udp" server, use routines s2 ureceive and s2 usend * in this file, instead of s2 receive and s2 send. * int s2 ureceive( sl, buffer, buflen, option ) * int s2 usend( sl, buffer, buflen, option ) * char * s2 upeername( sl, option ) * int s2 upeerport( sl, option ) * * If option is 1, error message is printed on to stderr * when error occured. * If option is 3, error and information message is printed on to * stderr when error occured. * Error codes errno returned from the system subroutines are * preserved on return to the caller. * * Bugs: * As global data will be used between s2 ureceive and s2 usend * in order to keep client's address, these routines must be paired * to distinguish the clients. * If the file descriptor 0 is closed between s2 sopen and s2 accept, * s2 accept may return 0 for the connection file descriptor. */ char comsubs what[] = "@(#)comsubs.c v1.3.3 tcp|udp server subroutines, K.Furukawa, Aug.1994"; /* **/ /** * s2 sopen * s2 sopen prepares communication server socket to accept a * a connection from a client. * * int s2 sopen( portnum, service, protocol, option ) * * if portnum is positive, try to open a server socket with protocol * then try to open with service name * then if portnum is negative, try to open with -portnum * if option is 1 error message is sent to stderr * if option is 3 error/information message is sent to stderr * * return: positive/0 success, socket descriptor * -1 S2 NOSERV service not found * -2 S2 NOPORT no port/service specified * -3 S2 NOHOST unknown host * -4 S2 NOPROT protocol other than tcp/udp specified * -5 S2 OPENERR socket open failure * -6 S2 BINDERR socket bind failure * -7 S2 CONNERR socket connect failure * -8 S2 LISNERR socket listen failure */ int s2 sopen( portnum, service, protocol, option ) int portnum; /* positive: port no, negative: default port */ char *service; /* service name, or null */ char *protocol; /* "tcp" or "udp" */ int option; /* option 1: error, 2: info. message */ /* **/ /** * s2 accept * s2 accept accepts a request from a client on the socket created * by s2 sopen call and establishes a connection. If multiple * thread is specified, it will fork child. * * int s2 accept( sl, flag, option ) * * sl is socket descriptor returned from s2 sopen. * if flag is 1 multiple thread will be generated and child process * accepts a connection. otherwise only one connection at a time * will be generated. * (on os9/msdos/vms flag has no effect, always single thread.) * if option is 1 error message is sent to stderr * if option is 3 error/information message is sent to stderr * * return: 0 success, parent process return * positive success, socket descriptor (for child process) * -9 S2 ACCPERR socket accept failure * -10 S2 FORKERR child fork failure */ int s2 accept( sl, flag, option ) int sl; /* socket descriptor for listen */ int flag; /* flag 1: multi-thread, 0: single thread */ int option; /* option 1: error, 2: info. message */ /* **/ /** * s2 sclose * s2 sclose close communication port of server side * * int s2 sclose( sd, option ) * * return: nothing */ int s2 sclose( sd, option ) int sd; /* socket descriptor returned from s2 open */ int option; /* option 1/2: error/information message */ /* **/ /** * s2 ureceive * s2 ureceive receives message from "udp" communication port * calls recvfrom(2) system call. * * int s2 ureceive(sl, buffer, buflen, option) * * return: -22 S2 RECVERR receive failure * positive byte count which has been received */ int s2 ureceive(sl, buffer, buflen, option) int sl; /* socket descriptor returned from s2 sopen */ char *buffer; /* buffer to receive */ int buflen; /* buffer length */ int option; /* option 1: error/information message */ /* **/ /** * s2 usend * s2 usend sends message to "udp" communication port * calls sendto(2) system call. * * int s2 usend(sl, buffer, buflen, option) * * return: -21 S2 SENDERR send failure * positive byte count which has been sent */ int s2 usend(sl, buffer, buflen, option) int sl; /* socket descriptor returned from s2 open */ char *buffer; /* buffer to send */ int buflen; /* buffer length */ int option; /* option 1/2: error/information message */ /* **/ /** * s2 upeername * s2 upeername returns the remote host name from which the "udp" * message is received. this function should be called just after * s2 ureceive() or s2 tureceive() call. * * char * s2 upeername(sn, option) * * return: host name or host address in dotted format * * if option is S2 OINFO, it prints remote information. */ char * s2 upeername( sn, option ) int sn; /* socket descriptor, not used */ int option; /* option 1: error, 2: info. message */ /* **/ /** * s2 upeerport * s2 upeerport returns the remote port number from which the "udp" * message is received. this function should be called just after * s2 ureceive() or s2 tureceive() call. * * int s2 upeerport(sn, option) * * return: remote port number in operation * * if option is S2 OINFO, it prints remote information. */ int s2 upeerport( sn, option ) int sn; /* socket descriptor, not used */ int option; /* option 1: error, 2: info. message */ /* **/ /** * comsubt -- communication subroutines with timeout * Kazuro Furukawa, KEK, Japan (furukawa@kek.jp) * (if you modified this code, please inform furukawa) * * K.Furukawa Nov.9.1988. (rwrite) * K.F Apr.13.1989. converted from rwrite (recho) * K.F Mar.19.1991. recho v3.4.2 * K.F Mar.24.1992. comsub * K.F Jun.12.1993. comsubt * Modifications * K.F Jun.12.1993. add s2 tureceive() and s2 tusend() * * This module defines send and receive rouine for socket communi- * cation. It can be used with timeout specification. If you * don't need timeout function, you may use s2 send and s2 receive. * Timeout value is specified in milli-seconds. * int s2 tsend( sd, buffer, buflen, timeout, option ) * int s2 treceive( sd, buffer, buflen, timeout, option ) * For udp server, you should use these functions instead. If you * don't need timeout function, you may use s2 usend and s2 ureceive. * int s2 tusend( sd, buffer, buflen, timeout, option ) * int s2 tureceive( sd, buffer, buflen, timeout, option ) * If option is 1, error message is printed on to stderr * when error occured. * If option is 3, error and information message is printed on to * stderr when error occured. * Error codes errno returned from the system subroutines are * preserved on return to the caller. * * Bugs: * not all environments are supported. ex. MSDOS is not supported. */ char comsubt what[] = "@(#)comsubt.c v1.1.0 tcp|udp client subroutines, K.Furukawa, Jun.1993"; /* **/ /** * s2 tsend * s2 tsend sends message to communication port with timeout * calls send(2) system call. * * int s2 tsend(sd, buffer, buflen, timeout, option) * * return: -21 S2 SENDERR send failure * -23 S2 SLCTERR select failure * -24 S2 TIMEOUT timeout failure * positive byte count which has been sent */ int s2 tsend(sd, buffer, buflen, timeout, option) int sd; /* socket descriptor returned from s2 open */ char *buffer; /* buffer to send */ int buflen; /* buffer length */ int timeout; /* timeout in milli-second */ int option; /* option 1/2: error/information message */ /* **/ /** * s2 treceive * s2 treceive receives message from communication port with timeout * calls recv(2) system call. * * int s2 treceive(sd, buffer, buflen, timeout, option) * * return: -22 S2 RECVERR receive failure * -23 S2 SLCTERR select failure * -24 S2 TIMEOUT timeout failure * positive byte count which has been received */ int s2 treceive(sd, buffer, buflen, timeout, option) int sd; /* socket descriptor returned from s2 open */ char *buffer; /* buffer to receive */ int buflen; /* buffer length */ int timeout; /* timeout in milli-second */ int option; /* option 1/2: error/information message */ /* **/ /** * s2 tureceive * s2 tureceive receives message from "udp" communication port with * timeout, calls recvfrom(2) system call. * * int s2 tureceive(sl, buffer, buflen, timeout, option) * * return: -22 S2 RECVERR receive failure * -23 S2 SLCTERR select failure * -24 S2 TIMEOUT timeout failure * positive byte count which has been received */ int s2 tureceive(sd, buffer, buflen, timeout, option) int sd; /* socket descriptor returned from s2 sopen */ char *buffer; /* buffer to receive */ int buflen; /* buffer length */ int timeout; /* timeout in milli-second */ int option; /* option 1: error/information message */ /* **/ /** * s2 tusend * s2 tusend sends message to "udp" communication port with timeout * calls sendto(2) system call. * * int s2 tusend(sl, buffer, buflen, timeout, option) * * return: -21 S2 SENDERR send failure * -23 S2 SLCTERR select failure * -24 S2 TIMEOUT timeout failure * positive byte count which has been sent */ int s2 tusend(sd, buffer, buflen, timeout, option) int sd; /* socket descriptor returned from s2 open */ char *buffer; /* buffer to send */ int buflen; /* buffer length */ int timeout; /* timeout in milli-second */ int option; /* option 1/2: error/information message */ /* **/ /** * comsubu -- communication subroutines for udp without connect * Kazuro Furukawa, KEK, Japan (furukawa@kek.jp) * (if you modified this code, please inform furukawa) * * K.Furukawa Nov.9.1988. (rwrite) * K.F Apr.13.1989. converted from rwrite (recho) * K.F Mar.19.1991. recho v3.4.2 * K.F Mar.24.1992.(2) comsub * K.F Sep.14.1992. add option 3 (bit 2) * K.F Mar.4.1994. udp without connection * Modifications * * This module is a re-writing of zechosub. * This module defines basic rouines for udp socket communication. * int s2 uopen( portnum, service, protocol, hostname, option ) * int s2 scuopen( destination, protocol, option ) * * You may use only one socket with uopen routines. * s2 bsend and s2 breceive routine can be used with these routines * * If option is 1, error message is printed on to stderr * when error occured. * If option is 3, error and information message is printed on to stderr * when error occured. * Error code errno returned from the system subroutines are preserved * on return to the caller. * For usage, see comsubs2.doc or example programs such as * s2 in2soc, etc. */ char comsubu what[] = "@(#)comsubu.c v1.0.2 udp client subroutines, K.Furukawa, Aug.1994"; /* **/ /** * s2 uopen * s2 uopen prepares udp communication socket without connection * * int s2 uopen( portnum, service, protocol, hostname, option ) * * this is based on s2 bopen * if portnum is positive, try to open a socket to hostname * with the portnum * then try to open with service * then if portnum is negative, try to open with -portnum * only "udp" protocol is meaningful for this routine * if option is 1 or S2 OERR, error message is sent to stderr * if option is 3 or S2 OALL, error/info. message is sent to stderr * if protocol is not "udp", S2 NOPROT is returned * * return: positive/0 success, socket descriptor * -1 S2 NOSERV service not found * -2 S2 NOPORT no port/service specified * -3 S2 NOHOST unknown host * -4 S2 NOPROT protocol other than udp specified * -5 S2 OPENERR socket open failure * -6 S2 UBNDERR udp bind failure/ broadcast assigning failure * -7 S2 CONNERR socket connect failure */ int s2 uopen( portnum, service, protocol, hostname, option ) int portnum; /* positive: port no, negative: default port */ char *service; /* service name, or null */ char *protocol; /* "udp" */ char *hostname; /* host name or ip-address */ int option; /* option 1: error, 2: info. message */ /* **/ /** * s2 scuopen * s2 scuopen prepares udp communication socket (sc open compatible) * * int s2 scuopen( destination, protocol, option ) * * destination is a string, one of these forms * "service name", "#port number", * "service name@host name", "#port number@host name" * if option is 1 or S2 OERR, error message is sent to stderr * if option is 3 or S2 OALL, error/info. message is sent to stderr * * return: positive/0 success, socket descriptor * -1 S2 NOSERV service not found * -2 S2 NOPORT no port/service specified * -3 S2 NOHOST unknown host * -4 S2 NOPROT protocol other than tcp/udp specified * -5 S2 OPENERR socket open failure * -6 S2 UBNDERR udp bind failure * -7 S2 CONNERR socket connect failure */ int s2 scuopen( destination, protocol, option ) char *destination; /* service and host */ char *protocol; /* "tcp" or "udp" */ int option; /* option 1: error, 2: info. message */ /* **/