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 / ioctl.c next >
C/C++ Source or Header  |  1997-10-08  |  7KB  |  250 lines

  1. /******************************************************************************\
  2. * ioctl.c - TCP server
  3. *
  4. *       This is a part of the Microsoft Source Code Samples.
  5. *       Copyright 1996-1997 Microsoft Corporation.
  6. *       All rights reserved.
  7. *       This source code is only intended as a supplement to
  8. *       Microsoft Development Tools and/or WinHelp documentation.
  9. *       See these sources for detailed information regarding the
  10. *       Microsoft samples programs.
  11. \******************************************************************************/
  12.  
  13.  
  14.  
  15. #define WIN32_LEAN_AND_MEAN
  16. #include <winsock2.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20.  
  21. #define DEFAULT_PORT 5001
  22.  
  23. int ReadAndEcho(SOCKET , char *,int ) ;
  24. int WriteMessage(SOCKET , char *,int ) ;
  25.  
  26. void Usage(char *progname) {
  27.     fprintf(stderr,"Usage\n%s -e [endpoint] -i [interface]\n",
  28.         progname);
  29.     fprintf(stderr,"Where:\n");
  30.     fprintf(stderr,"\tendpoint is the port to listen on\n");
  31.     fprintf(stderr,"\tinterface is the ipaddr (in dotted decimal notation)");
  32.     fprintf(stderr," to bind to\n");
  33.     fprintf(stderr,"Defaults are 5001 and INADDR_ANY\n");
  34.     WSACleanup();
  35.     exit(1);
  36. }
  37. int main(int argc, char **argv) {
  38.  
  39.     char Buffer[128];
  40.     char *interface= NULL;
  41.     unsigned short port=DEFAULT_PORT;
  42.     int fromlen;
  43.     int i, ioctl_opt =1;
  44.     struct sockaddr_in local, from;
  45.     WSADATA wsaData;
  46.     SOCKET listen_socket, msgsock;
  47.     fd_set readfds, writefds, exceptfds;
  48.  
  49.     /* Parse arguments */
  50.     if (argc >1) {
  51.         for(i=1;i <argc;i++) {
  52.             if ( (argv[i][0] == '-') || (argv[i][0] == '/') ) {
  53.                 switch(tolower(argv[i][1])) {
  54.                     case 'i':
  55.                         interface = argv[++i];
  56.                         break;
  57.                     case 'e':
  58.                         port = atoi(argv[++i]);
  59.                         break;
  60.                     default:
  61.                         Usage(argv[0]);
  62.                         break;
  63.                 }
  64.             }
  65.             else
  66.                 Usage(argv[0]);
  67.         }
  68.     }
  69.     
  70.     if (WSAStartup(0x202,&wsaData) == SOCKET_ERROR) {
  71.         fprintf(stderr,"WSAStartup failed with error %d\n",WSAGetLastError());
  72.         WSACleanup();
  73.         return -1;
  74.     }
  75.     
  76.     if (port == 0){
  77.         Usage(argv[0]);
  78.     }
  79.  
  80.     //
  81.     // The fd sets should be zeroed out before using them to prevent errors.
  82.     FD_ZERO(&readfds);
  83.     FD_ZERO(&writefds);
  84.     FD_ZERO(&exceptfds);
  85.     memset(Buffer,0,sizeof(Buffer));
  86.  
  87.     local.sin_family = AF_INET;
  88.  
  89.     //
  90.     // bind to specific interface if desired.
  91.  
  92.     local.sin_addr.s_addr = (!interface)?INADDR_ANY:inet_addr(interface); 
  93.  
  94.     /* 
  95.      * Port MUST be in Network Byte Order
  96.      */
  97.     local.sin_port = htons(port);
  98.  
  99.     listen_socket = socket(AF_INET, SOCK_STREAM,0); // TCP socket
  100.     if (listen_socket == INVALID_SOCKET){
  101.         fprintf(stderr,"socket() failed with error %d\n",WSAGetLastError());
  102.         WSACleanup();
  103.         return -1;
  104.     }
  105.     //
  106.     // bind() associates a local address and port combination with the
  107.     // socket just created. 
  108.  
  109.     if (bind(listen_socket,(struct sockaddr*)&local,sizeof(local) ) 
  110.         == SOCKET_ERROR) {
  111.         fprintf(stderr,"bind() failed with error %d\n",WSAGetLastError());
  112.         WSACleanup();
  113.         return -1;
  114.     }
  115.  
  116.     //
  117.     // start listening on the socket for incoming connections
  118.     //
  119.     if (listen(listen_socket,5) == SOCKET_ERROR) {
  120.         fprintf(stderr,"listen() failed with error %d\n",WSAGetLastError());
  121.         WSACleanup();
  122.         return -1;
  123.     }
  124.     printf("%s: Listening on port %d\n",argv[0],port);
  125.  
  126.     //
  127.     // Set the socket to non-blocking mode.
  128.     //
  129.     if (ioctlsocket(listen_socket,FIONBIO,&ioctl_opt) == SOCKET_ERROR) {
  130.         fprintf(stderr,"ioctlsocket failed %d\n",WSAGetLastError());
  131.         WSACleanup();
  132.         return -1;
  133.     }
  134.     //
  135.     // The structure of the loop below is very simple. We only accept one
  136.     // connection at a time. As soon as another client connects, we
  137.     // disconnect the first one, and start talking to the new client.
  138.     // All this server does is to echo the data received on the socket
  139.     // back to the client.
  140.     //
  141.     // This is not a very realistic server, but it does serve to show that
  142.     // select() does not scale very well on win32. If we were dealing
  143.     // with more than one client, we would have to have a list of sockets
  144.     // that are in each fdset to be able to check them when select()
  145.     // returns.
  146.     //
  147.     while(1) {
  148.  
  149.         //
  150.         // A socket in the listen() state becomes ready to read when a
  151.         // client connects to it. An accept() will complete without
  152.         // blocking.
  153.         // Since select sets the sockets that are ready to be read from or
  154.         // written to, we have to include listen_socket in the fdset each time
  155.         // through the loop.
  156.         //
  157.  
  158.         FD_SET(listen_socket,&readfds);
  159.  
  160.         i = select(0,&readfds,&writefds,&exceptfds,NULL);
  161.         if (i == SOCKET_ERROR) {
  162.             fprintf(stderr,"select failed %d\n",WSAGetLastError());
  163.         }
  164.         if (i==0){
  165.             fprintf(stderr,"Select returned no fds ready\n");
  166.         }
  167.  
  168.         if (FD_ISSET(listen_socket, &readfds)){
  169.             //
  170.             // close the previous client socket. 
  171.             // We must also clear it from the fdset to prevent select()
  172.             // from failing.
  173.             //
  174.             closesocket(msgsock);
  175.             FD_CLR(msgsock,&readfds);
  176.             FD_CLR(msgsock,&writefds);
  177.             fromlen = sizeof(from);
  178.             msgsock= accept(listen_socket,(struct sockaddr*)&from,&fromlen);
  179.             if (msgsock == INVALID_SOCKET) {
  180.                 fprintf(stderr,"accept failed %d\n",WSAGetLastError());
  181.                 WSACleanup();
  182.                 return -1;
  183.             }
  184.             FD_SET(msgsock,&writefds);
  185.             FD_SET(msgsock,&readfds);
  186.             continue;
  187.         }
  188.         if (FD_ISSET(msgsock,&readfds) ) {
  189.             //
  190.             // socket is ready to read, i.e., there is data on the socket.
  191.             //
  192.             if (ReadAndEcho(msgsock,Buffer,sizeof(Buffer))<0) {
  193.                 fprintf(stderr,"terminating connection\n");
  194.                 FD_CLR(msgsock,&readfds);
  195.                 FD_CLR(msgsock,&writefds);
  196.                 closesocket(msgsock);
  197.                 continue;
  198.             }
  199.         }
  200.         if (FD_ISSET(msgsock,&writefds) ){
  201.             if (WriteMessage(msgsock,Buffer,sizeof(Buffer)) <=0) {
  202.                 fprintf(stderr,"terminating connection\n");
  203.                 FD_CLR(msgsock,&readfds);
  204.                 FD_CLR(msgsock,&writefds);
  205.                 closesocket(msgsock);
  206.                 continue;
  207.             }
  208.         }
  209.         FD_SET(msgsock,&writefds);
  210.         FD_SET(msgsock,&readfds);
  211.     }
  212. }
  213. int ReadAndEcho(SOCKET insock, char *Buffer,int size) {
  214.     int rc;
  215.  
  216.     rc = recv(insock,Buffer,size,0);
  217.  
  218.     if (rc == SOCKET_ERROR) {
  219.         fprintf(stderr,"recv() failed with error %d\n",WSAGetLastError());    
  220.         return -1;
  221.     }
  222.     if (rc ==0) {
  223.         fprintf(stderr,"Connection closed by client\n");
  224.         return 0;
  225.     }
  226.     printf("Received [%s] from client\n",Buffer);
  227.     return rc;
  228. }
  229. int WriteMessage(SOCKET outsock, char *Buffer,int size) {
  230.     int rc;
  231.     int lasterr;
  232.  
  233.     printf("Sending [%s] to client\n",Buffer);
  234.     rc = send(outsock,Buffer,size, 0);
  235.  
  236.     if (rc == SOCKET_ERROR) {
  237.       lasterr = WSAGetLastError();
  238.       if (lasterr == WSAEWOULDBLOCK)
  239.         return 0;
  240.       else {
  241.         fprintf(stderr,"send() failed with error %d\n",lasterr);    
  242.         return -1;
  243.       }
  244.     }
  245.     if (rc ==0) {
  246.         fprintf(stderr,"Connection closed by client\n");
  247.     }
  248.     return rc;
  249. }
  250.