home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / viscobv6.zip / vac22os2 / ibmcobol / samples / toolkit / tcpiptk / echosamp / echosrv / echosmt.c < prev    next >
Text File  |  1996-11-19  |  8KB  |  258 lines

  1. /********************************************************copyrite.xic********/
  2. /*                                                                          */
  3. /*   Licensed Materials - Property of IBM                                   */
  4. /*   IBM TCP/IP for OS/2                                                    */
  5. /*   (C) Copyright IBM Corporation. 1996.                                   */
  6. /*                                                                          */
  7. /*   All rights reserved.                                                   */
  8. /*                                                                          */
  9. /*   US Government Users Restricted Rights -                                */
  10. /*   Use, duplication or disclosure restricted by GSA ADP Schedule          */
  11. /*   Contract with IBM Corp.                                                */
  12. /*                                                                          */
  13. /*--------------------------------------------------------------------------*/
  14. /*                                                                          */
  15. /*  DISCLAIMER OF WARRANTIES.  The following [enclosed] code is             */
  16. /*  sample code created by IBM Corporation. This sample code is not         */
  17. /*  part of any standard or IBM product and is provided to you solely       */
  18. /*  for  the purpose of assisting you in the development of your            */
  19. /*  applications.  The code is provided "AS IS", without                    */
  20. /*  warranty of any kind.  IBM shall not be liable for any damages          */
  21. /*  arising out of your use of the sample code, even if they have been      */
  22. /*  advised of the possibility of such damages.                             */
  23. /*--------------------------------------------------------------------------*/
  24.  
  25. /*****************************************************************************
  26. *
  27. * Multithreaded ECHO server
  28. * -------------------------
  29. *
  30. * Written by Andre Asselin
  31. *
  32. *
  33. * Description
  34. * -----------
  35. *
  36. * This program implements the server side of the Echo protocol (RFC 862).  The
  37. * Echo protocol is very simple: whatever the client sends to the server, the
  38. * server will send right back to the client.
  39. *
  40. * This version of the server will start a new thread for each TCP connection
  41. * it accepts.  The main thread is responsible for handling UDP echo requests
  42. * and for doing the accept() for each new TCP connection and spinning off a
  43. * thread to service it.
  44. *
  45. *************************************************************************/
  46.  
  47.  
  48. #include <stdlib.h>
  49.  
  50. #include <types.h>
  51. #include <netinet/in.h>
  52. #include <sys/socket.h>
  53. #include <netdb.h>
  54.  
  55. #define STACK_SIZE      65536
  56.  
  57. void ServiceUDP(int sock);
  58. void ServiceTCP(void *arg);
  59.  
  60.  
  61. void main(int argc, char **argv) {
  62.    int listen_sock, udp_sock, socks[2], newsock;
  63.    struct servent *echoprot;
  64.    struct sockaddr_in server, client;
  65.    int rc;
  66.    int asize;
  67.  
  68.    // Initialize TCP/IP
  69.    if (sock_init() != 0) {
  70.       printf("INET.SYS probably is not running");
  71.       exit(1);
  72.    }
  73.  
  74. //------ Create the TCP server socket
  75.  
  76.    // Create a TCP socket to accept incoming connections
  77.    listen_sock = socket(AF_INET, SOCK_STREAM, 0);
  78.    if (listen_sock == -1) {
  79.        psock_errno("tcp socket()");
  80.        exit(1);
  81.    }
  82.  
  83.    printf("TCP socket assigned is %d\n", listen_sock);
  84.  
  85.    // Get the port for the echo protocol out of the etc\services file
  86.    echoprot = getservbyname("echo", "tcp");
  87.    if (echoprot == NULL) {
  88.       printf("The echo/tcp protocol is not listed in the etc/services file\n");
  89.       exit(1);
  90.    }
  91.  
  92.    // Bind the TCP socket to the echo port
  93.    server.sin_family = AF_INET;   
  94.    server.sin_port = echoprot->s_port;
  95.    server.sin_addr.s_addr = INADDR_ANY;
  96.  
  97.    rc = bind(listen_sock, (struct sockaddr *)&server, sizeof(server));
  98.    if (rc == -1) {
  99.        psock_errno("tcp bind()");
  100.        exit(1);
  101.    }
  102.  
  103.    // Put the socket into listen mode
  104.  
  105.    rc = listen(listen_sock, SOMAXCONN);
  106.    if (rc == -1) {
  107.        psock_errno("listen()");
  108.        exit(1);
  109.    }
  110.  
  111. //------ Create the UDP server socket
  112.  
  113.    // Create a UDP socket to accept incoming data
  114.    udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
  115.    if (udp_sock == -1) {
  116.        psock_errno("udp socket()");
  117.        exit(1);
  118.    }
  119.  
  120.    printf("UDP socket assigned is %d\n", udp_sock);
  121.  
  122.    // Get the port for the echo protocol out of the etc\services file
  123.    echoprot = getservbyname("echo", "udp");
  124.    if (echoprot == NULL) {
  125.       printf("The echo/udp protocol is not listed in the etc/services file\n");
  126.       exit(1);
  127.    }
  128.  
  129.    // Bind the UDP socket to the echo port
  130.    server.sin_family = AF_INET;   
  131.    server.sin_port = echoprot->s_port;
  132.    server.sin_addr.s_addr = INADDR_ANY;
  133.  
  134.    rc = bind(udp_sock, (struct sockaddr *)&server, sizeof(server));
  135.    if (rc == -1) {
  136.        psock_errno("udp bind()");
  137.        exit(1);
  138.    }
  139.  
  140. //------ Wait for a connection on the TCP socket or a packet on the UDP socket
  141.  
  142.    while (1) {
  143.       // Setup the socket array for select()
  144.       socks[0] = listen_sock;
  145.       socks[1] = udp_sock;
  146.  
  147.       // Wait indefinitely
  148.       rc = select(socks, 2, 0, 0, -1);
  149.       if (rc == -1) {
  150.          // If the select was interrupted, just continue
  151.          if (sock_errno() == SOCEINTR)
  152.             continue;
  153.          psock_errno("main() select()");
  154.          exit(1);
  155.       }
  156.  
  157.       if (socks[0] != -1) {
  158.          // The TCP listen socket has a connection request ready-- accept() it
  159.  
  160.          asize = sizeof(client);
  161.          newsock = accept(socks[0], (struct sockaddr *)&client, &asize);
  162.          if (newsock == -1) {
  163.             psock_errno("accept()");
  164.             exit(1);
  165.          }
  166.  
  167.          printf("Received a TCP connection on socket %d from %s port %d\n",
  168.                 newsock, inet_ntoa(client.sin_addr), ntohs(client.sin_port));
  169.  
  170.          // Start a new thread and pass it the socket it should service
  171.  
  172.          rc = _beginthread(ServiceTCP, 0, STACK_SIZE, (void *)newsock);
  173.          if (rc == -1) {
  174.             printf("_beginthread() failed\n");
  175.             exit(1);
  176.          }
  177.       }
  178.  
  179.       // If the UDP socket has a packet waiting, service it
  180.  
  181.       if (socks[1] != -1)
  182.          ServiceUDP(socks[1]);
  183.    }
  184. }
  185.  
  186.  
  187. // The UDP socket has a packet waiting to be received-- receive it and echo
  188. // it back to the sender
  189.  
  190. void ServiceUDP(int sock) {
  191.    static char buf[32767];
  192.    int rc;
  193.    int asize, len;
  194.    struct sockaddr_in client;
  195.  
  196.    // Receive the packet
  197.  
  198.    asize = sizeof(client);
  199.    len = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&client,
  200.                   &asize);
  201.    if (len == -1) {
  202.       psock_errno("recvfrom()");
  203.       exit(1);
  204.    }
  205.  
  206.    printf("Received a UDP echo request from %s port %d\n",
  207.           inet_ntoa(client.sin_addr), ntohs(client.sin_port));
  208.  
  209.    // Echo it back
  210.  
  211.    rc = sendto(sock, buf, len, 0, (struct sockaddr *)&client, sizeof(client));
  212.    if (rc == -1 || rc != len) {
  213.       psock_errno("sendto()");
  214.       exit(1);
  215.    }
  216. }
  217.  
  218.  
  219. // A client initiated a TCP connection.  Echo any data he sends us back to him.
  220.  
  221. void ServiceTCP(void *arg) {
  222.    int rc, len;
  223.    char buf[1024];
  224.    int sock;
  225.  
  226.    // Convert the parameter to something we can use
  227.  
  228.    sock = (int)arg;
  229.  
  230.    // Do this until the client closes the connection
  231.  
  232.    while (1) {
  233.  
  234.       // Wait until there's some data available
  235.  
  236.       len = recv(sock, buf, sizeof(buf), 0);
  237.       if (len == -1) {
  238.          psock_errno("recv()");
  239.          exit(1);
  240.       }
  241.  
  242.       if (len == 0) {
  243.          printf("TCP socket %d: The client broke the connection\n", sock);
  244.          break;
  245.       }
  246.  
  247.       printf("TCP socket %d: received %d bytes\n", sock, len);
  248.  
  249.       // Send the data back
  250.  
  251.       rc = send(sock, buf, len, 0);
  252.       if (rc == -1) {
  253.          psock_errno("send()");
  254.          exit(1);
  255.       }
  256.    }
  257. }
  258.