home *** CD-ROM | disk | FTP | other *** search
- From: koreth@panarthea.EBay.Sun.COM (Steven Grimm)
- Newsgroups: alt.sources
- Subject: [tcp-ip] Easy-to-use socket library (was Re: Sockets vs streams. An attempt to answer the original question)
- Message-ID: <1990Sep16.015024.19314@math.lsa.umich.edu>
- Date: 16 Sep 90 01:50:24 GMT
-
- Archive-name: socket/30-Aug-90
- Original-posting-by: koreth@panarthea.EBay.Sun.COM (Steven Grimm)
- Original-subject: Easy-to-use socket library (was Re: Sockets vs streams. An attempt to answer the original question)
- Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)
-
- [Reposted from comp.protocols.tcp-ip.
- Comments on this service to emv@math.lsa.umich.edu (Edward Vielmetti).]
-
- henry@zoo.toronto.edu (Henry Spencer) writes:
- >(I find
- >it impossible to comprehend why 4BSD doesn't have an open-connection-to-
- >service-X-on-machine-Y library function, given how stereotyped and how
- >messy this job is)
-
- I wrote just such a library a few years ago; lots of people have found it
- very useful. Here it is again; everyone should feel free to pass it on
- and use it in whatever they like. There is no separate man page, but there
- are comments at the start of each function, which should be adequate.
-
- ---
- " !" - Marcel Marceau
- Steven Grimm Moderator, comp.{sources,binaries}.atari.st
- koreth@ebay.sun.com ...!sun!ebay!koreth
-
- ---
- /*
- ** SOCKET.C
- **
- ** Written by Steven Grimm (koreth@ebay.sun.com) on 11-26-87
- ** Please distribute widely, but leave my name here.
- **
- ** Various black-box routines for socket manipulation, so you don't have to
- ** remember all the structure elements.
- */
-
- #include <sys/types.h>
- #include <sys/time.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- #include <stdio.h>
- #include <ctype.h>
-
- #ifndef FD_SET /* for 4.2BSD */
- #define FD_SETSIZE (sizeof(fd_set) * 8)
- #define FD_SET(n, p) (((fd_set *) (p))->fds_bits[0] |= (1 << ((n) % 32)))
- #define FD_CLR(n, p) (((fd_set *) (p))->fds_bits[0] &= ~(1 << ((n) % 32)))
- #define FD_ISSET(n, p) (((fd_set *) (p))->fds_bits[0] & (1 << ((n) % 32)))
- #define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
- #endif
-
- extern int errno;
-
- /*
- ** serversock()
- **
- ** Creates an internet socket, binds it to an address, and prepares it for
- ** subsequent accept() calls by calling listen().
- **
- ** Input: port number desired, or 0 for a random one
- ** Output: file descriptor of socket, or a negative error
- */
- int serversock(port)
- int port;
- {
- int sock, x;
- struct sockaddr_in server;
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock < 0)
- return -errno;
-
- bzero(&server, sizeof(server));
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = INADDR_ANY;
- server.sin_port = htons(port);
-
- x = bind(sock, &server, sizeof(server));
- if (x < 0)
- {
- close(sock);
- return -errno;
- }
-
- listen(sock, 5);
-
- return sock;
- }
-
- /*
- ** portnum()
- **
- ** Returns the internet port number for a socket.
- **
- ** Input: file descriptor of socket
- ** Output: inet port number
- */
- int portnum(fd)
- int fd;
- {
- int length, err;
- struct sockaddr_in address;
-
- length = sizeof(address);
- err = getsockname(fd, &address, &length);
- if (err < 0)
- return -errno;
-
- return ntohs(address.sin_port);
- }
-
- /*
- ** clientsock()
- **
- ** Returns a connected client socket.
- **
- ** Input: host name and port number to connect to
- ** Output: file descriptor of CONNECTED socket, or a negative error (-9999
- ** if the hostname was bad).
- */
- int clientsock(host, port)
- char *host;
- int port;
- {
- int sock;
- struct sockaddr_in server;
- struct hostent *hp, *gethostbyname();
-
- bzero(&server, sizeof(server));
- server.sin_family = AF_INET;
- server.sin_port = htons(port);
-
- if (isdigit(host[0]))
- server.sin_addr.s_addr = inet_addr(host);
- else
- {
- hp = gethostbyname(host);
- if (hp == NULL)
- return -9999;
- bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
- }
-
- sock = socket(AF_INET, SOCK_STREAM, 0);
- if (sock < 0)
- return -errno;
-
- if (connect(sock, &server, sizeof(server)) < 0)
- {
- close(sock);
- return -errno;
- }
-
- return sock;
- }
-
- /*
- ** readable()
- **
- ** Poll a socket for pending input. Returns immediately. This is a front-end
- ** to waitread() below.
- **
- ** Input: file descriptor to poll
- ** Output: 1 if data is available for reading
- */
- readable(fd)
- int fd;
- {
- return(waitread(fd, 0));
- }
-
- /*
- ** waitread()
- **
- ** Wait for data on a file descriptor for a little while.
- **
- ** Input: file descriptor to watch
- ** how long to wait, in seconds, before returning
- ** Output: 1 if data was available
- ** 0 if the timer expired or a signal occurred.
- */
- waitread(fd, time)
- int fd, time;
- {
- fd_set readbits, other;
- struct timeval timer;
- int ret;
-
- timerclear(&timer);
- timer.tv_sec = time;
- FD_ZERO(&readbits);
- FD_ZERO(&other);
- FD_SET(fd, &readbits);
-
- ret = select(fd+1, &readbits, &other, &other, &timer);
- if (FD_ISSET(fd, &readbits))
- return 1;
- return 0;
- }
-