home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / tcpiptk / echosamp / echosrv / echosmt.c < prev    next >
Text File  |  1999-05-11  |  8KB  |  263 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. #include <stdio.h>
  50.  
  51. #include <types.h>
  52. #include <netinet/in.h>
  53. #include <sys/socket.h>
  54. #include <netdb.h>
  55. #include <sys\time.h>
  56. #include <unistd.h>
  57. #include <arpa\inet.h>
  58. #include <nerrno.h>
  59.  
  60. #define STACK_SIZE      65536
  61.  
  62. void ServiceUDP(int sock);
  63. void ServiceTCP(void *arg);
  64.  
  65.  
  66. void main(int argc, char **argv) {
  67.    int listen_sock, udp_sock, socks[2], newsock;
  68.    struct servent *echoprot;
  69.    struct sockaddr_in server, client;
  70.    int rc;
  71.    int asize;
  72.  
  73.    // Initialize TCP/IP
  74.    if (sock_init() != 0) {
  75.       printf("INET.SYS probably is not running");
  76.       exit(1);
  77.    }
  78.  
  79. //------ Create the TCP server socket
  80.  
  81.    // Create a TCP socket to accept incoming connections
  82.    listen_sock = socket(AF_INET, SOCK_STREAM, 0);
  83.    if (listen_sock == -1) {
  84.        psock_errno("tcp socket()");
  85.        exit(1);
  86.    }
  87.  
  88.    printf("TCP socket assigned is %d\n", listen_sock);
  89.  
  90.    // Get the port for the echo protocol out of the etc\services file
  91.    echoprot = getservbyname("echo", "tcp");
  92.    if (echoprot == NULL) {
  93.       printf("The echo/tcp protocol is not listed in the etc/services file\n");
  94.       exit(1);
  95.    }
  96.  
  97.    // Bind the TCP socket to the echo port
  98.    server.sin_family = AF_INET;
  99.    server.sin_port = echoprot->s_port;
  100.    server.sin_addr.s_addr = INADDR_ANY;
  101.  
  102.    rc = bind(listen_sock, (struct sockaddr *)&server, sizeof(server));
  103.    if (rc == -1) {
  104.        psock_errno("tcp bind()");
  105.        exit(1);
  106.    }
  107.  
  108.    // Put the socket into listen mode
  109.  
  110.    rc = listen(listen_sock, SOMAXCONN);
  111.    if (rc == -1) {
  112.        psock_errno("listen()");
  113.        exit(1);
  114.    }
  115.  
  116. //------ Create the UDP server socket
  117.  
  118.    // Create a UDP socket to accept incoming data
  119.    udp_sock = socket(AF_INET, SOCK_DGRAM, 0);
  120.    if (udp_sock == -1) {
  121.        psock_errno("udp socket()");
  122.        exit(1);
  123.    }
  124.  
  125.    printf("UDP socket assigned is %d\n", udp_sock);
  126.  
  127.    // Get the port for the echo protocol out of the etc\services file
  128.    echoprot = getservbyname("echo", "udp");
  129.    if (echoprot == NULL) {
  130.       printf("The echo/udp protocol is not listed in the etc/services file\n");
  131.       exit(1);
  132.    }
  133.  
  134.    // Bind the UDP socket to the echo port
  135.    server.sin_family = AF_INET;
  136.    server.sin_port = echoprot->s_port;
  137.    server.sin_addr.s_addr = INADDR_ANY;
  138.  
  139.    rc = bind(udp_sock, (struct sockaddr *)&server, sizeof(server));
  140.    if (rc == -1) {
  141.        psock_errno("udp bind()");
  142.        exit(1);
  143.    }
  144.  
  145. //------ Wait for a connection on the TCP socket or a packet on the UDP socket
  146.  
  147.    while (1) {
  148.       // Setup the socket array for select()
  149.       socks[0] = listen_sock;
  150.       socks[1] = udp_sock;
  151.  
  152.       // Wait indefinitely
  153.       rc = os2_select(socks, 2, 0, 0, -1);
  154.       if (rc == -1) {
  155.          // If the select was interrupted, just continue
  156.          if (sock_errno() == SOCEINTR)
  157.             continue;
  158.          psock_errno("main() select()");
  159.          exit(1);
  160.       }
  161.  
  162.       if (socks[0] != -1) {
  163.          // The TCP listen socket has a connection request ready-- accept() it
  164.  
  165.          asize = sizeof(client);
  166.          newsock = accept(socks[0], (struct sockaddr *)&client, &asize);
  167.          if (newsock == -1) {
  168.             psock_errno("accept()");
  169.             exit(1);
  170.          }
  171.  
  172.          printf("Received a TCP connection on socket %d from %s port %d\n",
  173.                 newsock, inet_ntoa(client.sin_addr), ntohs(client.sin_port));
  174.  
  175.          // Start a new thread and pass it the socket it should service
  176.  
  177.          rc = _beginthread(ServiceTCP, 0, STACK_SIZE, (void *)newsock);
  178.          if (rc == -1) {
  179.             printf("_beginthread() failed\n");
  180.             exit(1);
  181.          }
  182.       }
  183.  
  184.       // If the UDP socket has a packet waiting, service it
  185.  
  186.       if (socks[1] != -1)
  187.          ServiceUDP(socks[1]);
  188.    }
  189. }
  190.  
  191.  
  192. // The UDP socket has a packet waiting to be received-- receive it and echo
  193. // it back to the sender
  194.  
  195. void ServiceUDP(int sock) {
  196.    static char buf[32767];
  197.    int rc;
  198.    int asize, len;
  199.    struct sockaddr_in client;
  200.  
  201.    // Receive the packet
  202.  
  203.    asize = sizeof(client);
  204.    len = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&client,
  205.                   &asize);
  206.    if (len == -1) {
  207.       psock_errno("recvfrom()");
  208.       exit(1);
  209.    }
  210.  
  211.    printf("Received a UDP echo request from %s port %d\n",
  212.           inet_ntoa(client.sin_addr), ntohs(client.sin_port));
  213.  
  214.    // Echo it back
  215.  
  216.    rc = sendto(sock, buf, len, 0, (struct sockaddr *)&client, sizeof(client));
  217.    if (rc == -1 || rc != len) {
  218.       psock_errno("sendto()");
  219.       exit(1);
  220.    }
  221. }
  222.  
  223.  
  224. // A client initiated a TCP connection.  Echo any data he sends us back to him.
  225.  
  226. void ServiceTCP(void *arg) {
  227.    int rc, len;
  228.    char buf[1024];
  229.    int sock;
  230.  
  231.    // Convert the parameter to something we can use
  232.  
  233.    sock = (int)arg;
  234.  
  235.    // Do this until the client closes the connection
  236.  
  237.    while (1) {
  238.  
  239.       // Wait until there's some data available
  240.  
  241.       len = recv(sock, buf, sizeof(buf), 0);
  242.       if (len == -1) {
  243.          psock_errno("recv()");
  244.          exit(1);
  245.       }
  246.  
  247.       if (len == 0) {
  248.          printf("TCP socket %d: The client broke the connection\n", sock);
  249.          break;
  250.       }
  251.  
  252.       printf("TCP socket %d: received %d bytes\n", sock, len);
  253.  
  254.       // Send the data back
  255.  
  256.       rc = send(sock, buf, len, 0);
  257.       if (rc == -1) {
  258.          psock_errno("send()");
  259.          exit(1);
  260.       }
  261.    }
  262. }
  263.