home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / netds / winsock / simple / simples.c < prev   
C/C++ Source or Header  |  1997-10-08  |  6KB  |  196 lines

  1. /******************************************************************************\
  2. * simples.c - Simple TCP/UDP server using Winsock 1.1
  3. *       This is a part of the Microsoft Source Code Samples.
  4. *       Copyright 1996-1997 Microsoft Corporation.
  5. *       All rights reserved.
  6. *       This source code is only intended as a supplement to
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. #define WIN32_LEAN_AND_MEAN
  13. #include <winsock2.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17.  
  18. #define DEFAULT_PORT 5001
  19. #define DEFAULT_PROTO SOCK_STREAM // TCP
  20.  
  21. void Usage(char *progname) {
  22.     fprintf(stderr,"Usage\n%s -p [protocol] -e [endpoint] -i [interface]\n",
  23.         progname);
  24.     fprintf(stderr,"Where:\n\tprotocol is one of TCP or UDP\n");
  25.     fprintf(stderr,"\tendpoint is the port to listen on\n");
  26.     fprintf(stderr,"\tinterface is the ipaddr (in dotted decimal notation)");
  27.     fprintf(stderr," to bind to\n");
  28.     fprintf(stderr,"Defaults are TCP,5001 and INADDR_ANY\n");
  29.     WSACleanup();
  30.     exit(1);
  31. }
  32. int main(int argc, char **argv) {
  33.  
  34.     char Buffer[128];
  35.     char *interface= NULL;
  36.     unsigned short port=DEFAULT_PORT;
  37.     int retval;
  38.     int fromlen;
  39.     int i;
  40.     int socket_type = DEFAULT_PROTO;
  41.     struct sockaddr_in local, from;
  42.     WSADATA wsaData;
  43.     SOCKET listen_socket, msgsock;
  44.  
  45.     /* Parse arguments */
  46.     if (argc >1) {
  47.         for(i=1;i <argc;i++) {
  48.             if ( (argv[i][0] == '-') || (argv[i][0] == '/') ) {
  49.                 switch(tolower(argv[i][1])) {
  50.                     case 'p':
  51.                         if (!stricmp(argv[i+1], "TCP") )
  52.                             socket_type = SOCK_STREAM;
  53.                         else if (!stricmp(argv[i+1], "UDP") )
  54.                             socket_type = SOCK_DGRAM;
  55.                         else
  56.                             Usage(argv[0]);
  57.                         i++;
  58.                         break;
  59.  
  60.                     case 'i':
  61.                         interface = argv[++i];
  62.                         break;
  63.                     case 'e':
  64.                         port = atoi(argv[++i]);
  65.                         break;
  66.                     default:
  67.                         Usage(argv[0]);
  68.                         break;
  69.                 }
  70.             }
  71.             else
  72.                 Usage(argv[0]);
  73.         }
  74.     }
  75.     
  76.     if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) {
  77.         fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError());
  78.         WSACleanup();
  79.         return -1;
  80.     }
  81.     
  82.     if (port == 0){
  83.         Usage(argv[0]);
  84.     }
  85.  
  86.     local.sin_family = AF_INET;
  87.     local.sin_addr.s_addr = (!interface)?INADDR_ANY:inet_addr(interface); 
  88.  
  89.     /* 
  90.      * Port MUST be in Network Byte Order
  91.      */
  92.     local.sin_port = htons(port);
  93.  
  94.     listen_socket = socket(AF_INET, socket_type,0); // TCP socket
  95.     
  96.     if (listen_socket == INVALID_SOCKET){
  97.         fprintf(stderr,"socket() failed with error %d\n",WSAGetLastError());
  98.         WSACleanup();
  99.         return -1;
  100.     }
  101.     //
  102.     // bind() associates a local address and port combination with the
  103.     // socket just created. This is most useful when the application is a 
  104.     // server that has a well-known port that clients know about in advance.
  105.     //
  106.  
  107.     if (bind(listen_socket,(struct sockaddr*)&local,sizeof(local) ) 
  108.         == SOCKET_ERROR) {
  109.         fprintf(stderr,"bind() failed with error %d\n",WSAGetLastError());
  110.         WSACleanup();
  111.         return -1;
  112.     }
  113.  
  114.     //
  115.     // So far, everything we did was applicable to TCP as well as UDP.
  116.     // However, there are certain steps that do not work when the server is
  117.     // using UDP.
  118.     //
  119.  
  120.     // We cannot listen() on a UDP socket.
  121.  
  122.     if (socket_type != SOCK_DGRAM) {
  123.         if (listen(listen_socket,5) == SOCKET_ERROR) {
  124.             fprintf(stderr,"listen() failed with error %d\n",WSAGetLastError());
  125.             WSACleanup();
  126.             return -1;
  127.         }
  128.     }
  129.     printf("%s: 'Listening' on port %d, protocol %s\n",argv[0],port,
  130.         (socket_type == SOCK_STREAM)?"TCP":"UDP");
  131.     while(1) {
  132.         fromlen =sizeof(from);
  133.         //
  134.         // accept() doesn't make sense on UDP, since we do not listen()
  135.         //
  136.         if (socket_type != SOCK_DGRAM) {
  137.             msgsock = accept(listen_socket,(struct sockaddr*)&from, &fromlen);
  138.             if (msgsock == INVALID_SOCKET) {
  139.                 fprintf(stderr,"accept() error %d\n",WSAGetLastError());
  140.                 WSACleanup();
  141.                 return -1;
  142.             }
  143.             printf("accepted connection from %s, port %d\n", 
  144.                         inet_ntoa(from.sin_addr),
  145.                         htons(from.sin_port)) ;
  146.             
  147.         }
  148.         else
  149.             msgsock = listen_socket;
  150.  
  151.         //
  152.         // In the case of SOCK_STREAM, the server can do recv() and 
  153.         // send() on the accepted socket and then close it.
  154.  
  155.         // However, for SOCK_DGRAM (UDP), the server will do
  156.         // recvfrom() and sendto()  in a loop.
  157.  
  158.         if (socket_type != SOCK_DGRAM)
  159.             retval = recv(msgsock,Buffer,sizeof (Buffer),0 );
  160.         else {
  161.             retval = recvfrom(msgsock,Buffer,sizeof (Buffer),0,
  162.                 (struct sockaddr *)&from,&fromlen);
  163.             printf("Received datagram from %s\n",inet_ntoa(from.sin_addr));
  164.         }
  165.             
  166.         if (retval == SOCKET_ERROR) {
  167.             fprintf(stderr,"recv() failed: error %d\n",WSAGetLastError());
  168.             closesocket(msgsock);
  169.             continue;
  170.         }
  171.         if (retval == 0) {
  172.             printf("Client closed connection\n");
  173.             closesocket(msgsock);
  174.             continue;
  175.         }
  176.         printf("Received %d bytes, data [%s] from client\n",retval,Buffer);
  177.  
  178.         printf("Echoing same data back to client\n");
  179.         if (socket_type != SOCK_DGRAM)
  180.             retval = send(msgsock,Buffer,sizeof(Buffer),0);
  181.         else
  182.             retval = sendto(msgsock,Buffer,sizeof (Buffer),0,
  183.                 (struct sockaddr *)&from,fromlen);
  184.         if (retval == SOCKET_ERROR) {
  185.             fprintf(stderr,"send() failed: error %d\n",WSAGetLastError());
  186.         }
  187.         if (socket_type != SOCK_DGRAM){
  188.             printf("Terminating connection\n");
  189.             closesocket(msgsock);
  190.         }
  191.         else 
  192.             printf("UDP server looping back for more requests\n");
  193.         continue;
  194.     }
  195. }
  196.