server.c
上传用户:hldy006
上传日期:2015-05-15
资源大小:1189k
文件大小:15k
源码类别:

浏览器

开发平台:

Others

  1. //
  2. // server.c - Simple TCP/UDP server using Winsock 2.2
  3. //
  4. //      This is a part of the Microsoft Source Code Samples.
  5. //      Copyright 1996 - 2000 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. #define WIN32_LEAN_AND_MEAN
  13. #include <winsock2.h>
  14. #include <ws2tcpip.h>
  15. #include <tpipv6.h>  // For IPv6 Tech Preview.
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. //
  20. // This code assumes that at the transport level, the system only supports
  21. // one stream protocol (TCP) and one datagram protocol (UDP).  Therefore,
  22. // specifying a socket type of SOCK_STREAM is equivalent to specifying TCP
  23. // and specifying a socket type of SOCK_DGRAM is equivalent to specifying UDP.
  24. //
  25. #define DEFAULT_FAMILY     PF_UNSPEC // Accept either IPv4 or IPv6
  26. #define DEFAULT_SOCKTYPE   SOCK_STREAM // TCP
  27. #define DEFAULT_PORT       "5001" // Arbitrary, albiet a historical test port
  28. #define BUFFER_SIZE        64 // Set very small for demonstration purposes
  29. void Usage(char *ProgName) {
  30.     fprintf(stderr, "nSimple socket sample server program.n");
  31.     fprintf(stderr, "n%s [-f family] [-t transport] [-p port] [-a address]nn",
  32.             ProgName);
  33.     fprintf(stderr, "  familytOne of PF_INET, PF_INET6 or PF_UNSPEC.  (default %s)n",
  34.             (DEFAULT_FAMILY == PF_UNSPEC) ? "PF_UNSPEC" :
  35.             ((DEFAULT_FAMILY == PF_INET) ? "PF_INET" : "PF_INET6"));
  36.     fprintf(stderr, "  transporttEither TCP or UDP.  (default: %s)n",
  37.             (DEFAULT_SOCKTYPE == SOCK_STREAM) ? "TCP" : "UDP");
  38.     fprintf(stderr, "  portttPort on which to bind.  (default %s)n",
  39.             DEFAULT_PORT);
  40.     fprintf(stderr, "  addresstIP address on which to bind.  (default: unspecified address)n");
  41.     WSACleanup();
  42.     exit(1);
  43. }
  44. LPSTR DecodeError(int ErrorCode)
  45. {
  46.     static char Message[1024];
  47.     // If this program was multi-threaded, we'd want to use
  48.     // FORMAT_MESSAGE_ALLOCATE_BUFFER instead of a static buffer here.
  49.     // (And of course, free the buffer when we were done with it)
  50.     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
  51.                   FORMAT_MESSAGE_MAX_WIDTH_MASK, NULL, ErrorCode,
  52.                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  53.                   (LPSTR)Message, 1024, NULL);
  54.     return Message;
  55. }
  56. int main(int argc, char **argv)
  57. {
  58.     char Buffer[BUFFER_SIZE], Hostname[NI_MAXHOST];
  59.     int Family = DEFAULT_FAMILY;
  60.     int SocketType = DEFAULT_SOCKTYPE;
  61.     char *Port = DEFAULT_PORT;
  62.     char *Address = NULL;
  63.     int i, NumSocks, RetVal, FromLen, AmountRead;
  64.     SOCKADDR_STORAGE From;
  65.     WSADATA wsaData;
  66.     ADDRINFO Hints, *AddrInfo, *AI;
  67.     SOCKET ServSock[FD_SETSIZE];
  68.     fd_set SockSet;
  69.     // Parse arguments
  70.     if (argc > 1) {
  71.         for(i = 1;i < argc; i++) {
  72.             if ((argv[i][0] == '-') || (argv[i][0] == '/') &&
  73.                 (argv[i][1] != 0) && (argv[i][2] == 0)) {
  74.                 switch(tolower(argv[i][1])) {
  75.                     case 'f':
  76.                         if (!argv[i+1])
  77.                             Usage(argv[0]);
  78.                         if (!stricmp(argv[i+1], "PF_INET"))
  79.                             Family = PF_INET;
  80.                         else if (!stricmp(argv[i+1], "PF_INET6"))
  81.                             Family = PF_INET6;
  82.                         else if (!stricmp(argv[i+1], "PF_UNSPEC"))
  83.                             Family = PF_UNSPEC;
  84.                         else
  85.                             Usage(argv[0]);
  86.                         i++;
  87.                         break;
  88.                     case 't':
  89.                         if (!argv[i+1])
  90.                             Usage(argv[0]);
  91.                         if (!stricmp(argv[i+1], "TCP"))
  92.                             SocketType = SOCK_STREAM;
  93.                         else if (!stricmp(argv[i+1], "UDP"))
  94.                             SocketType = SOCK_DGRAM;
  95.                         else
  96.                             Usage(argv[0]);
  97.                         i++;
  98.                         break;
  99.                     case 'a':
  100.                         if (argv[i+1]) {
  101.                             if (argv[i+1][0] != '-') {
  102.                                 Address = argv[++i];
  103.                                 break;
  104.                             }
  105.                         }
  106.                         Usage(argv[0]);
  107.                         break;
  108.                     case 'p':
  109.                         if (argv[i+1]) {
  110.                             if (argv[i+1][0] != '-') {
  111.                                 Port = argv[++i];
  112.                                 break;
  113.                             }
  114.                         }
  115.                         Usage(argv[0]);
  116.                         break;
  117.                     default:
  118.                         Usage(argv[0]);
  119.                         break;
  120.                 }
  121.             } else
  122.                 Usage(argv[0]);
  123.         }
  124.     }
  125.     
  126.     // Ask for Winsock version 2.2.
  127.     if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) {
  128.         fprintf(stderr, "WSAStartup failed with error %d: %sn",
  129.                 RetVal, DecodeError(RetVal));
  130.         WSACleanup();
  131.         return -1;
  132.     }
  133.     
  134.     if (Port == NULL) {
  135.         Usage(argv[0]);
  136.     }
  137.     //
  138.     // By setting the AI_PASSIVE flag in the hints to getaddrinfo, we're
  139.     // indicating that we intend to use the resulting address(es) to bind
  140.     // to a socket(s) for accepting incoming connections.  This means that
  141.     // when the Address parameter is NULL, getaddrinfo will return one
  142.     // entry per allowed protocol family containing the unspecified address
  143.     // for that family.
  144.     //
  145.     memset(&Hints, 0, sizeof(Hints));
  146.     Hints.ai_family = Family;
  147.     Hints.ai_socktype = SocketType;
  148.     Hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
  149.     RetVal = getaddrinfo(Address, Port, &Hints, &AddrInfo);
  150.     if (RetVal != 0) {
  151.         fprintf(stderr, "getaddrinfo failed with error %d: %sn",
  152.                 RetVal, gai_strerror(RetVal));
  153.         WSACleanup();
  154.         return -1;
  155.     }
  156.     //
  157.     // For each address getaddrinfo returned, we create a new socket,
  158.     // bind that address to it, and create a queue to listen on.
  159.     //
  160.     for (i = 0, AI = AddrInfo; AI != NULL; AI = AI->ai_next, i++) {
  161.         // Highly unlikely, but check anyway.
  162.         if (i == FD_SETSIZE) {
  163.             printf("getaddrinfo returned more addresses than we could use.n");
  164.             break;
  165.         }
  166.         // This example only supports PF_INET and PF_INET6.
  167.         if ((AI->ai_family != PF_INET) && (AI->ai_family != PF_INET6))
  168.             continue;
  169.         // Open a socket with the correct address family for this address.
  170.         ServSock[i] = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
  171.         if (ServSock[i] == INVALID_SOCKET){
  172.             fprintf(stderr, "socket() failed with error %d: %sn",
  173.                     WSAGetLastError(), DecodeError(WSAGetLastError()));
  174.             continue;
  175.         }
  176.         //
  177.         // bind() associates a local address and port combination
  178.         // with the socket just created. This is most useful when
  179.         // the application is a server that has a well-known port
  180.         // that clients know about in advance.
  181.         //
  182.         if (bind(ServSock[i], AI->ai_addr, AI->ai_addrlen) == SOCKET_ERROR) {
  183.             fprintf(stderr,"bind() failed with error %d: %sn",
  184.                     WSAGetLastError(), DecodeError(WSAGetLastError()));
  185.             continue;
  186.         }
  187.         //
  188.         // So far, everything we did was applicable to TCP as well as UDP.
  189.         // However, there are certain fundamental differences between stream
  190.         // protocols such as TCP and datagram protocols such as UDP.
  191.         //
  192.         // Only connection orientated sockets, for example those of type
  193.         // SOCK_STREAM, can listen() for incoming connections.
  194.         //
  195.         if (SocketType == SOCK_STREAM) {
  196.             if (listen(ServSock[i], 5) == SOCKET_ERROR) {
  197.                 fprintf(stderr, "listen() failed with error %d: %sn",
  198.                         WSAGetLastError(), DecodeError(WSAGetLastError()));
  199.                 continue;
  200.             }
  201.         }
  202.         printf("'Listening' on port %s, protocol %s, protocol family %sn",
  203.                Port, (SocketType == SOCK_STREAM) ? "TCP" : "UDP",
  204.                (AI->ai_family == PF_INET) ? "PF_INET" : "PF_INET6");
  205.     }
  206.     freeaddrinfo(AddrInfo);
  207.     if (i == 0) {
  208.         fprintf(stderr, "Fatal error: unable to serve on any address.n");
  209.         WSACleanup();
  210.         return -1;
  211.     }
  212.     NumSocks = i;
  213.     //
  214.     // We now put the server into an eternal loop,
  215.     // serving requests as they arrive.
  216.     //
  217.     FD_ZERO(&SockSet);
  218.     while(1) {
  219.         FromLen = sizeof(From);
  220.         //
  221.         // For connection orientated protocols, we will handle the
  222.         // packets comprising a connection collectively.  For datagram
  223.         // protocols, we have to handle each datagram individually.
  224.         //
  225.         //
  226.         // Check to see if we have any sockets remaining to be served
  227.         // from previous time through this loop.  If not, call select()
  228.         // to wait for a connection request or a datagram to arrive.
  229.         //
  230.         for (i = 0; i < NumSocks; i++){
  231.             if (FD_ISSET(ServSock[i], &SockSet))
  232.                 break;
  233.         }
  234.         if (i == NumSocks) {
  235.             for (i = 0; i < NumSocks; i++)
  236.                 FD_SET(ServSock[i], &SockSet);
  237.             if (select(NumSocks, &SockSet, 0, 0, 0) == SOCKET_ERROR) {
  238.                 fprintf(stderr, "select() failed with error %d: %sn",
  239.                         WSAGetLastError(), DecodeError(WSAGetLastError()));
  240.                 WSACleanup();
  241.                 return -1;
  242.             }
  243.         }
  244.         for (i = 0; i < NumSocks; i++){
  245.             if (FD_ISSET(ServSock[i], &SockSet)) {
  246.                 FD_CLR(ServSock[i], &SockSet);
  247.                 break;
  248.             }
  249.         }
  250.         if (SocketType == SOCK_STREAM) {
  251.             SOCKET ConnSock;
  252.             //
  253.             // Since this socket was returned by the select(), we know we
  254.             // have a connection waiting and that this accept() won't block.
  255.             //
  256.             ConnSock = accept(ServSock[i], (LPSOCKADDR)&From, &FromLen);
  257.             if (ConnSock == INVALID_SOCKET) {
  258.                 fprintf(stderr, "accept() failed with error %d: %sn",
  259.                         WSAGetLastError(), DecodeError(WSAGetLastError()));
  260.                 WSACleanup();
  261.                 return -1;
  262.             }
  263.             if (getnameinfo((LPSOCKADDR)&From, FromLen, Hostname,
  264.                             sizeof(Hostname), NULL, 0, NI_NUMERICHOST) != 0)
  265.                 strcpy(Hostname, "<unknown>");
  266.             printf("nAccepted connection from %sn", Hostname);
  267.             
  268.             //
  269.             // This sample server only handles connections sequentially.
  270.             // To handle multiple connections simultaneously, a server
  271.             // would likely want to launch another thread or process at this
  272.             // point to handle each individual connection.  Alternatively,
  273.             // it could keep a socket per connection and use select()
  274.             // on the fd_set to determine which to read from next.
  275.             //
  276.             // Here we just loop until this connection terminates.
  277.             //
  278.             while (1) {
  279.                 //
  280.                 // We now read in data from the client.  Because TCP
  281.                 // does NOT maintain message boundaries, we may recv()
  282.                 // the client's data grouped differently than it was
  283.                 // sent.  Since all this server does is echo the data it
  284.                 // receives back to the client, we don't need to concern
  285.                 // ourselves about message boundaries.  But it does mean
  286.                 // that the message data we print for a particular recv()
  287.                 // below may contain more or less data than was contained
  288.                 // in a particular client send().
  289.                 //
  290.                 AmountRead = recv(ConnSock, Buffer, sizeof(Buffer), 0);
  291.                 if (AmountRead == SOCKET_ERROR) {
  292.                     fprintf(stderr, "recv() failed with error %d: %sn",
  293.                             WSAGetLastError(), DecodeError(WSAGetLastError()));
  294.                     closesocket(ConnSock);
  295.                     break;
  296.                 }
  297.                 if (AmountRead == 0) {
  298.                     printf("Client closed connectionn");
  299.                     closesocket(ConnSock);
  300.                     break;
  301.                 }
  302.                 printf("Received %d bytes from client: [%.*s]n",
  303.                        AmountRead, AmountRead, Buffer);
  304.                 printf("Echoing same data back to clientn");
  305.                 RetVal = send(ConnSock, Buffer, AmountRead, 0);
  306.                 if (RetVal == SOCKET_ERROR) {
  307.                     fprintf(stderr, "send() failed: error %d: %sn",
  308.                             WSAGetLastError(), DecodeError(WSAGetLastError()));
  309.                     closesocket(ConnSock);
  310.                     break;
  311.                 }
  312.             }
  313.         } else {
  314.             //
  315.             // Since UDP maintains message boundaries, the amount of data
  316.             // we get from a recvfrom() should match exactly the amount of
  317.             // data the client sent in the corresponding sendto().
  318.             //
  319.             AmountRead = recvfrom(ServSock[i], Buffer, sizeof(Buffer), 0,
  320.                                   (LPSOCKADDR)&From, &FromLen);
  321.             if (AmountRead == SOCKET_ERROR) {
  322.                 fprintf(stderr, "recvfrom() failed with error %d: %sn",
  323.                         WSAGetLastError(), DecodeError(WSAGetLastError()));
  324.                 closesocket(ServSock[i]);
  325.                 break;
  326.             }
  327.             if (AmountRead == 0) {
  328.                 // This should never happen on an unconnected socket, but...
  329.                 printf("recvfrom() returned zero, abortingn");
  330.                 closesocket(ServSock[i]);
  331.                 break;
  332.             }
  333.             
  334.             RetVal = getnameinfo((LPSOCKADDR)&From, FromLen, Hostname,
  335.                                  sizeof(Hostname), NULL, 0, NI_NUMERICHOST);
  336.             if (RetVal != 0) {
  337.                 fprintf(stderr, "getnameinfo() failed with error %d: %sn",
  338.                         RetVal, DecodeError(RetVal));
  339.                 strcpy(Hostname, "<unknown>");
  340.             }
  341.             printf("Received a %d byte datagram from %s: [%.*s]n",
  342.                    AmountRead, Hostname, AmountRead, Buffer);
  343.             printf("Echoing same data back to clientn");
  344.             RetVal = sendto(ServSock[i], Buffer, AmountRead, 0,
  345.                             (LPSOCKADDR)&From, FromLen);
  346.             if (RetVal == SOCKET_ERROR) {
  347.                 fprintf(stderr, "send() failed with error %d: %sn",
  348.                         WSAGetLastError(), DecodeError(WSAGetLastError()));
  349.             }
  350.         }
  351.     }
  352.     return 0;
  353. }