home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / sockdemo / isockl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-12  |  4.0 KB  |  143 lines

  1. /* isockl.c -- set up an INTERNET STREAM socket and listen on it */
  2. /* (C) 1991 Blair P. Houghton, All Rights Reserved, copying and */
  3. /* distribution permitted with copyright intact.        */
  4.  
  5. /* a stream (a socket opened using SOCK_STREAM) requires the use of
  6. listen() and accept() in a receiver, and connect() in a sender */
  7.  
  8. #include <stdio.h>
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <netinet/in.h>
  12. #include <fcntl.h>
  13.  
  14. #ifdef __STDC__
  15. extern void    exit( int );
  16. extern void    perror( char * );
  17. extern int    printf( char *, ... );
  18. extern int    bind( int, struct sockaddr *, int );
  19. extern int    socket( int, int, int );
  20. extern int    read( int, char *, unsigned );
  21. extern char *    strcpy( char *, char *b );
  22. extern int    fcntl( int, int, int );
  23. extern int    accept( int, struct sockaddr *, int * );
  24. extern int    listen( int, int );
  25. extern int    unlink( char * );
  26. extern int    getsockname( int, struct sockaddr *, int * );
  27.  
  28. void main( int argc, char *argv[] )
  29. #else
  30. main( argc, argv )
  31. int argc; char *argv[];
  32. #endif
  33. {
  34.     int sock;                /* fd for the listening socket */
  35.     int ear;                /* fd for the working socket */
  36.     struct sockaddr_in sockaddr;    /* sytem's location of the socket */
  37.     struct sockaddr_in caller;        /* id of foreign calling process */
  38.     int sockaddr_in_length = sizeof(struct sockaddr_in);
  39.     char buf[BUFSIZ];
  40.     int read_ret;
  41.     int fromlen = sizeof(struct sockaddr_in);
  42.     char acknowledgement[BUFSIZ];
  43.  
  44.     /*
  45.      *  open a net socket, using stream (file-style i/o)
  46.      *  mode, with protocol irrelevant ( == 0 )
  47.      */
  48.     if ( (sock = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) {
  49.     char s[BUFSIZ];
  50.     sprintf( s, "%s: can't assign fd for socket", argv[0] );
  51.     perror(s);
  52.     exit(__LINE__);
  53.     }
  54.  
  55.    /*
  56.     *  register the socket
  57.     */
  58.     sockaddr.sin_family = AF_INET;
  59.     sockaddr.sin_addr.s_addr = INADDR_ANY;    /* not choosy about who calls */
  60.     sockaddr.sin_port = 0;
  61.  
  62.     if ( bind( sock, (struct sockaddr *) &sockaddr, sizeof sockaddr ) < 0 ) {
  63.     char s[BUFSIZ];
  64.     sprintf( s, "%s: can't bind socket (%d)", argv[0], sock );
  65.     perror(s);
  66.     exit(__LINE__);
  67.     }
  68.  
  69.    /*
  70.     *  get port number
  71.     */
  72.     if ( getsockname( sock, (struct sockaddr *) &sockaddr,
  73.               (int *)&sockaddr_in_length )
  74.      < 0 ) {
  75.     char s[BUFSIZ];
  76.     sprintf( s, "%s: can't get port number of socket (%d)",
  77.         argv[0], sock );
  78.     perror(s);
  79.     exit(__LINE__);
  80.     }
  81.  
  82.     printf("opened socket as fd (%d) on port (%d) for stream i/o\n",
  83.         sock, ntohs(sockaddr.sin_port) );
  84.  
  85.     printf(
  86. "struct sockaddr_in {\n\
  87.     sin_family        = %d\n\
  88.     sin_addr.s_addr    = %d\n\
  89.     sin_port        = %d\n\
  90. } sockaddr;\n"
  91. , sockaddr.sin_family
  92. , sockaddr.sin_addr.s_addr
  93. , ntohs(sockaddr.sin_port)
  94.     );
  95.  
  96.  
  97.     /* put an ear to the socket, listening for a knock-knock-knocking */
  98.     listen( sock, 1 );                /* 1: only one queue slot */
  99.     /* ear will be a temporary (non-reusable) socket different from sock */
  100.     if ( (ear = accept( sock, (struct sockaddr *)&caller, &fromlen )) < 0 ) {
  101.     perror(argv[0]);
  102.     exit(__LINE__);
  103.     }
  104.  
  105.     /* print calling process' identification */
  106.     printf(
  107. "struct sockaddr_in {\n\
  108.     sin_family        = %d\n\
  109.     sin_addr.s_addr    = %s\n\
  110.     sin_port (!!!)    = %d\n\
  111. } caller;\n"
  112. , caller.sin_family
  113. , inet_ntoa(caller.sin_addr)
  114. /* , caller.sin_addr.s_addr -- gives an unsigned long, not a struct in_addr */
  115. , ntohs(caller.sin_port)
  116.     );
  117.  
  118.     /* optional ack; demonstrates bidirectionality */
  119.     gethostname(buf, sizeof buf);
  120.     sprintf( acknowledgement, "Welcome, from sunny %s (%s.%d)\n",
  121.         buf,
  122.         buf,
  123.         ntohs(sockaddr.sin_port)
  124.         );
  125.     /* write into the ear; the sock is _only_for_rendezvous_ */
  126.     if ( write ( ear, acknowledgement, sizeof acknowledgement ) < 1 )
  127.     perror(argv[0]);
  128.  
  129.     /* read lines until the stream closes */
  130.     while ( (read_ret = read( ear, buf, sizeof buf )) > 0 )
  131.     printf( "%s: read from socket as follows:\n(%s)\n", argv[0], buf ); 
  132.  
  133.     if ( read_ret < 0 ) {
  134.     char s[BUFSIZ];
  135.     sprintf( s, "%s: error reading socket", argv[0] );
  136.     perror(s);
  137.     exit(__LINE__);
  138.     }
  139.  
  140.     /* loop ended normally:  read() returned NULL */
  141.     exit(0);
  142. }
  143.