home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1826 < prev    next >
Internet Message Format  |  1990-12-28  |  5KB

  1. From: koreth@panarthea.EBay.Sun.COM (Steven Grimm)
  2. Newsgroups: alt.sources
  3. Subject: [tcp-ip] Easy-to-use socket library (was Re: Sockets vs streams. An attempt to answer the original question)
  4. Message-ID: <1990Sep16.015024.19314@math.lsa.umich.edu>
  5. Date: 16 Sep 90 01:50:24 GMT
  6.  
  7. Archive-name: socket/30-Aug-90
  8. Original-posting-by: koreth@panarthea.EBay.Sun.COM (Steven Grimm)
  9. Original-subject: Easy-to-use socket library (was Re: Sockets vs streams. An attempt to answer the original question)
  10. Reposted-by: emv@math.lsa.umich.edu (Edward Vielmetti)
  11.  
  12. [Reposted from comp.protocols.tcp-ip.
  13. Comments on this service to emv@math.lsa.umich.edu (Edward Vielmetti).]
  14.  
  15. henry@zoo.toronto.edu (Henry Spencer) writes:
  16. >(I find
  17. >it impossible to comprehend why 4BSD doesn't have an open-connection-to-
  18. >service-X-on-machine-Y library function, given how stereotyped and how
  19. >messy this job is)
  20.  
  21. I wrote just such a library a few years ago; lots of people have found it
  22. very useful.  Here it is again; everyone should feel free to pass it on
  23. and use it in whatever they like.  There is no separate man page, but there
  24. are comments at the start of each function, which should be adequate.
  25.  
  26. ---
  27. "                                                  !" - Marcel Marceau
  28. Steven Grimm        Moderator, comp.{sources,binaries}.atari.st
  29. koreth@ebay.sun.com    ...!sun!ebay!koreth
  30.  
  31. ---
  32. /*
  33. ** SOCKET.C
  34. **
  35. ** Written by Steven Grimm (koreth@ebay.sun.com) on 11-26-87
  36. ** Please distribute widely, but leave my name here.
  37. **
  38. ** Various black-box routines for socket manipulation, so you don't have to
  39. ** remember all the structure elements.
  40. */
  41.  
  42. #include <sys/types.h>
  43. #include <sys/time.h>
  44. #include <sys/socket.h>
  45. #include <netinet/in.h>
  46. #include <arpa/inet.h>
  47. #include <netdb.h>
  48. #include <stdio.h>
  49. #include <ctype.h>
  50.  
  51. #ifndef FD_SET        /* for 4.2BSD */
  52. #define FD_SETSIZE      (sizeof(fd_set) * 8)
  53. #define FD_SET(n, p)    (((fd_set *) (p))->fds_bits[0] |= (1 << ((n) % 32)))
  54. #define FD_CLR(n, p)    (((fd_set *) (p))->fds_bits[0] &= ~(1 << ((n) % 32)))
  55. #define FD_ISSET(n, p)  (((fd_set *) (p))->fds_bits[0] & (1 << ((n) % 32)))
  56. #define FD_ZERO(p)      bzero((char *)(p), sizeof(*(p)))
  57. #endif
  58.  
  59. extern int errno;
  60.  
  61. /*
  62. ** serversock()
  63. **
  64. ** Creates an internet socket, binds it to an address, and prepares it for
  65. ** subsequent accept() calls by calling listen().
  66. **
  67. ** Input: port number desired, or 0 for a random one
  68. ** Output: file descriptor of socket, or a negative error
  69. */
  70. int serversock(port)
  71. int port;
  72. {
  73.     int    sock, x;
  74.     struct    sockaddr_in server;
  75.  
  76.     sock = socket(AF_INET, SOCK_STREAM, 0);
  77.     if (sock < 0)
  78.         return -errno;
  79.  
  80.     bzero(&server, sizeof(server));
  81.     server.sin_family = AF_INET;
  82.     server.sin_addr.s_addr = INADDR_ANY;
  83.     server.sin_port = htons(port);
  84.  
  85.     x = bind(sock, &server, sizeof(server));
  86.     if (x < 0)
  87.     {
  88.         close(sock);
  89.         return -errno;
  90.     }
  91.  
  92.     listen(sock, 5);
  93.  
  94.     return sock;
  95. }
  96.  
  97. /*
  98. ** portnum()
  99. **
  100. ** Returns the internet port number for a socket.
  101. **
  102. ** Input: file descriptor of socket
  103. ** Output: inet port number
  104. */
  105. int portnum(fd)
  106. int fd;
  107. {
  108.     int    length, err;
  109.     struct    sockaddr_in address;
  110.  
  111.     length = sizeof(address);
  112.     err = getsockname(fd, &address, &length);
  113.     if (err < 0)
  114.         return -errno;
  115.  
  116.     return ntohs(address.sin_port);
  117. }
  118.  
  119. /*
  120. ** clientsock()
  121. **
  122. ** Returns a connected client socket.
  123. **
  124. ** Input: host name and port number to connect to
  125. ** Output: file descriptor of CONNECTED socket, or a negative error (-9999
  126. **         if the hostname was bad).
  127. */
  128. int clientsock(host, port)
  129. char *host;
  130. int port;
  131. {
  132.     int    sock;
  133.     struct    sockaddr_in server;
  134.     struct    hostent *hp, *gethostbyname();
  135.  
  136.     bzero(&server, sizeof(server));
  137.     server.sin_family = AF_INET;
  138.     server.sin_port = htons(port);
  139.  
  140.     if (isdigit(host[0]))
  141.         server.sin_addr.s_addr = inet_addr(host);
  142.     else
  143.     {
  144.         hp = gethostbyname(host);
  145.         if (hp == NULL)
  146.             return -9999;
  147.         bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
  148.     }
  149.  
  150.     sock = socket(AF_INET, SOCK_STREAM, 0);
  151.     if (sock < 0)
  152.         return -errno;
  153.  
  154.     if (connect(sock, &server, sizeof(server)) < 0)
  155.     {
  156.         close(sock);
  157.         return -errno;
  158.     }
  159.  
  160.     return sock;
  161. }
  162.  
  163. /*
  164. ** readable()
  165. **
  166. ** Poll a socket for pending input.  Returns immediately.  This is a front-end
  167. ** to waitread() below.
  168. **
  169. ** Input: file descriptor to poll
  170. ** Output: 1 if data is available for reading
  171. */
  172. readable(fd)
  173. int fd;
  174. {
  175.     return(waitread(fd, 0));
  176. }
  177.  
  178. /*
  179. ** waitread()
  180. **
  181. ** Wait for data on a file descriptor for a little while.
  182. **
  183. ** Input: file descriptor to watch
  184. **      how long to wait, in seconds, before returning
  185. ** Output: 1 if data was available
  186. **       0 if the timer expired or a signal occurred.
  187. */
  188. waitread(fd, time)
  189. int fd, time;
  190. {
  191.     fd_set readbits, other;
  192.     struct timeval timer;
  193.     int ret;
  194.  
  195.     timerclear(&timer);
  196.     timer.tv_sec = time;
  197.     FD_ZERO(&readbits);
  198.     FD_ZERO(&other);
  199.     FD_SET(fd, &readbits);
  200.  
  201.     ret = select(fd+1, &readbits, &other, &other, &timer);
  202.     if (FD_ISSET(fd, &readbits))
  203.         return 1;
  204.     return 0;
  205. }
  206.