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

浏览器

开发平台:

Others

  1. //
  2. // client.c - Simple TCP/UDP client 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_SERVER     NULL // Will use the loopback interface
  26. #define DEFAULT_FAMILY     PF_UNSPEC // Accept either IPv4 or IPv6
  27. #define DEFAULT_SOCKTYPE   SOCK_STREAM // TCP
  28. #define DEFAULT_PORT       "5001" // Arbitrary, albiet a historical test port
  29. #define DEFAULT_EXTRA      0 // Number of "extra" bytes to send
  30. #define BUFFER_SIZE        65536
  31. void Usage(char *ProgName) {
  32.     fprintf(stderr, "nSimple socket sample client program.n");
  33.     fprintf(stderr, "n%s [-s server] [-f family] [-t transport] [-p port] [-b bytes] [-n number]nn",
  34.             ProgName);
  35.     fprintf(stderr, "  servertServer name or IP address.  (default: %s)n",
  36.             (DEFAULT_SERVER == NULL) ? "loopback address" : DEFAULT_SERVER);
  37.     fprintf(stderr, "  familytOne of PF_INET, PF_INET6 or PF_UNSPEC.  (default: %s)n",
  38.             (DEFAULT_FAMILY == PF_UNSPEC) ? "PF_UNSPEC" :
  39.             ((DEFAULT_FAMILY == PF_INET) ? "PF_INET" : "PF_INET6"));
  40.     fprintf(stderr, "  transporttEither TCP or UDP.  (default: %s)n",
  41.             (DEFAULT_SOCKTYPE == SOCK_STREAM) ? "TCP" : "UDP");
  42.     fprintf(stderr, "  portttPort on which to connect.  (default: %s)n",
  43.             DEFAULT_PORT);
  44.     fprintf(stderr, "  bytesttBytes of extra data to send.  (default: %d)n",
  45.             DEFAULT_EXTRA);
  46.     fprintf(stderr, "  numbertNumber of sends to perform.  (default: 1)n");
  47.     fprintf(stderr, "  (-n by itself makes client run in an infinite loop,");
  48.     fprintf(stderr, " Hit Ctrl-C to terminate)n");
  49.     WSACleanup();
  50.     exit(1);
  51. }
  52. LPSTR DecodeError(int ErrorCode)
  53. {
  54.     static char Message[1024];
  55.     // If this program was multi-threaded, we'd want to use
  56.     // FORMAT_MESSAGE_ALLOCATE_BUFFER instead of a static buffer here.
  57.     // (And of course, free the buffer when we were done with it)
  58.     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
  59.                   FORMAT_MESSAGE_MAX_WIDTH_MASK,
  60.                   NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  61.                   (LPSTR)Message, 1024, NULL);
  62.     return Message;
  63. }
  64. int
  65. ReceiveAndPrint(SOCKET ConnSocket, char *Buffer, int BufLen)
  66. {
  67.     int AmountRead;
  68.     AmountRead = recv(ConnSocket, Buffer, BufLen, 0);
  69.     if (AmountRead == SOCKET_ERROR) {
  70.         fprintf(stderr, "recv() failed with error %d: %sn", 
  71.                 WSAGetLastError(), DecodeError(WSAGetLastError()));
  72.         closesocket(ConnSocket);
  73.         WSACleanup();
  74.         exit(1);
  75.     }
  76.     //
  77.     // We are not likely to see this with UDP, since there is no
  78.     // 'connection' established. 
  79.     //
  80.     if (AmountRead == 0) {
  81.         printf("Server closed connectionn");
  82.         closesocket(ConnSocket);
  83.         WSACleanup();
  84.         exit(0);
  85.     }
  86.     printf("Received %d bytes from server: [%.*s]n",
  87.            AmountRead, AmountRead, Buffer);
  88.     return AmountRead;
  89. }
  90. int main(int argc, char **argv) {
  91.     char Buffer[BUFFER_SIZE], AddrName[NI_MAXHOST];
  92.     char *Server = DEFAULT_SERVER;
  93.     int Family = DEFAULT_FAMILY;
  94.     int SocketType = DEFAULT_SOCKTYPE;
  95.     char *Port = DEFAULT_PORT;
  96.     int i, RetVal, AddrLen, AmountToSend;
  97.     int ExtraBytes = DEFAULT_EXTRA;
  98.     unsigned int Iteration, MaxIterations = 1;
  99.     BOOL RunForever = FALSE;
  100.     WSADATA wsaData;
  101.     ADDRINFO Hints, *AddrInfo, *AI;
  102.     SOCKET ConnSocket;
  103.     struct sockaddr_storage Addr;
  104.     if (argc > 1) {
  105.         for (i = 1;i < argc; i++) {
  106.             if (((argv[i][0] == '-') || (argv[i][0] == '/')) &&
  107.                 (argv[i][1] != 0) && (argv[i][2] == 0)) {
  108.                 switch(tolower(argv[i][1])) {
  109.                     case 'f':
  110.                         if (!argv[i+1])
  111.                             Usage(argv[0]);
  112.                         if (!stricmp(argv[i+1], "PF_INET"))
  113.                             Family = PF_INET;
  114.                         else if (!stricmp(argv[i+1], "PF_INET6"))
  115.                             Family = PF_INET6;
  116.                         else if (!stricmp(argv[i+1], "PF_UNSPEC"))
  117.                             Family = PF_UNSPEC;
  118.                         else
  119.                             Usage(argv[0]);
  120.                         i++;
  121.                         break;
  122.                     case 't':
  123.                         if (!argv[i+1])
  124.                             Usage(argv[0]);
  125.                         if (!stricmp(argv[i+1], "TCP"))
  126.                             SocketType = SOCK_STREAM;
  127.                         else if (!stricmp(argv[i+1], "UDP"))
  128.                             SocketType = SOCK_DGRAM;
  129.                         else
  130.                             Usage(argv[0]);
  131.                         i++;
  132.                         break;
  133.                     case 's':
  134.                         if (argv[i+1]) {
  135.                             if (argv[i+1][0] != '-') {
  136.                                 Server = argv[++i];
  137.                                 break;
  138.                             }
  139.                         }
  140.                         Usage(argv[0]);
  141.                         break;
  142.                     case 'p':
  143.                         if (argv[i+1]) {
  144.                             if (argv[i+1][0] != '-') {
  145.                                 Port = argv[++i];
  146.                                 break;
  147.                             }
  148.                         }
  149.                         Usage(argv[0]);
  150.                         break;
  151.                     case 'b':
  152.                         if (argv[i+1]) {
  153.                             if (argv[i+1][0] != '-') {
  154.                                 ExtraBytes = atoi(argv[++i]);
  155.                                 if (ExtraBytes > sizeof(Buffer) - sizeof("Message #4294967295"))
  156.                                     Usage(argv[0]);
  157.                                 break;
  158.                             }
  159.                         }
  160.                         Usage(argv[0]);
  161.                         break;
  162.                     case 'n':
  163.                         if (argv[i+1]) {
  164.                             if (argv[i+1][0] != '-') {
  165.                                 MaxIterations = atoi(argv[++i]);
  166.                                 break;
  167.                             }
  168.                         }
  169.                         RunForever = TRUE;
  170.                         break;
  171.                     default:
  172.                         Usage(argv[0]);
  173.                         break;
  174.                 }
  175.             }
  176.             else
  177.                 Usage(argv[0]);
  178.         }
  179.     }
  180.     // Ask for Winsock version 2.2.
  181.     if ((RetVal = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0) {
  182.         fprintf(stderr, "WSAStartup failed with error %d: %sn",
  183.                 RetVal, DecodeError(RetVal));
  184.         WSACleanup();
  185.         return -1;
  186.     }
  187.     //
  188.     // By not setting the AI_PASSIVE flag in the hints to getaddrinfo, we're
  189.     // indicating that we intend to use the resulting address(es) to connect
  190.     // to a service.  This means that when the Server parameter is NULL,
  191.     // getaddrinfo will return one entry per allowed protocol family
  192.     // containing the loopback address for that family.
  193.     //
  194.     
  195.     memset(&Hints, 0, sizeof(Hints));
  196.     Hints.ai_family = Family;
  197.     Hints.ai_socktype = SocketType;
  198.     RetVal = getaddrinfo(Server, Port, &Hints, &AddrInfo);
  199.     if (RetVal != 0) {
  200.         fprintf(stderr, "Cannot resolve address [%s] and port [%s], error %d: %sn",
  201.                 Server, Port, RetVal, gai_strerror(RetVal));
  202.         WSACleanup();
  203.         return -1;
  204.     }
  205.     //
  206.     // Try each address getaddrinfo returned, until we find one to which
  207.     // we can sucessfully connect.
  208.     //
  209.     for (AI = AddrInfo; AI != NULL; AI = AI->ai_next) {
  210.         // Open a socket with the correct address family for this address.
  211.         ConnSocket = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol);
  212.         if (ConnSocket == INVALID_SOCKET) {
  213.             fprintf(stderr,"Error Opening socket, error %d: %sn",
  214.                     WSAGetLastError(), DecodeError(WSAGetLastError()));
  215.             continue;
  216.         }
  217.         //
  218.         // Notice that nothing in this code is specific to whether we 
  219.         // are using UDP or TCP.
  220.         //
  221.         // When connect() is called on a datagram socket, it does not 
  222.         // actually establish the connection as a stream (TCP) socket
  223.         // would. Instead, TCP/IP establishes the remote half of the
  224.         // (LocalIPAddress, LocalPort, RemoteIP, RemotePort) mapping.
  225.         // This enables us to use send() and recv() on datagram sockets,
  226.         // instead of recvfrom() and sendto().
  227.         //
  228.         printf("Attempting to connect to: %sn", Server ? Server : "localhost");
  229.         if (connect(ConnSocket, AI->ai_addr, AI->ai_addrlen) != SOCKET_ERROR)
  230.             break;
  231.         i = WSAGetLastError();
  232.         if (getnameinfo(AI->ai_addr, AI->ai_addrlen, AddrName,
  233.                         sizeof(AddrName), NULL, 0, NI_NUMERICHOST) != 0)
  234.             strcpy(AddrName, "<unknown>");
  235.         fprintf(stderr, "connect() to %s failed with error %d: %sn",
  236.                 AddrName, i, DecodeError(i));
  237.     }
  238.     if (AI == NULL) {
  239.         fprintf(stderr, "Fatal error: unable to connect to the server.n");
  240.         WSACleanup();
  241.         return -1;
  242.     }
  243.     //
  244.     // This demonstrates how to determine to where a socket is connected.
  245.     //
  246.     AddrLen = sizeof(Addr);
  247.     if (getpeername(ConnSocket, (LPSOCKADDR)&Addr, &AddrLen) == SOCKET_ERROR) {
  248.         fprintf(stderr, "getpeername() failed with error %d: %sn",
  249.                 WSAGetLastError(), DecodeError(WSAGetLastError()));
  250.     } else {
  251.         if (getnameinfo((LPSOCKADDR)&Addr, AddrLen, AddrName,
  252.                         sizeof(AddrName), NULL, 0, NI_NUMERICHOST) != 0)
  253.             strcpy(AddrName, "<unknown>");
  254.         printf("Connected to %s, port %d, protocol %s, protocol family %sn",
  255.                AddrName, ntohs(SS_PORT(&Addr)),
  256.                (AI->ai_socktype == SOCK_STREAM) ? "TCP" : "UDP",
  257.                (AI->ai_family == PF_INET) ? "PF_INET" : "PF_INET6");
  258.     }
  259.     // We are done with the address info chain, so we can free it.
  260.     freeaddrinfo(AddrInfo);
  261.     //
  262.     // Find out what local address and port the system picked for us.
  263.     //
  264.     AddrLen = sizeof(Addr);
  265.     if (getsockname(ConnSocket, (LPSOCKADDR)&Addr, &AddrLen) == SOCKET_ERROR) {
  266.         fprintf(stderr, "getsockname() failed with error %d: %sn",
  267.                 WSAGetLastError(), DecodeError(WSAGetLastError()));
  268.     } else {
  269.         if (getnameinfo((LPSOCKADDR)&Addr, AddrLen, AddrName,
  270.                         sizeof(AddrName), NULL, 0, NI_NUMERICHOST) != 0)
  271.             strcpy(AddrName, "<unknown>");
  272.         printf("Using local address %s, port %dn",
  273.                AddrName, ntohs(SS_PORT(&Addr)));
  274.     }
  275.     //
  276.     // Send and receive in a loop for the requested number of iterations.
  277.     //
  278.     for (Iteration = 0; RunForever || Iteration < MaxIterations; Iteration++) {
  279.         // Compose a message to send.
  280.         AmountToSend = sprintf(Buffer, "Message #%u", Iteration + 1);
  281.         for (i = 0; i < ExtraBytes; i++) {
  282.             Buffer[AmountToSend++] = (char)((i & 0x3f) + 0x20);
  283.         }
  284.         // Send the message.  Since we are using a blocking socket, this
  285.         // call shouldn't return until it's able to send the entire amount.
  286.         RetVal = send(ConnSocket, Buffer, AmountToSend, 0);
  287.         if (RetVal == SOCKET_ERROR) {
  288.             fprintf(stderr, "send() failed with error %d: %sn",
  289.                     WSAGetLastError(), DecodeError(WSAGetLastError()));
  290.             WSACleanup();
  291.             return -1;
  292.         }
  293.         printf("Sent %d bytes (out of %d bytes) of data: [%.*s]n",
  294.                RetVal, AmountToSend, AmountToSend, Buffer);
  295.         // Clear buffer just to prove we're really receiving something.
  296.         memset(Buffer, 0, sizeof(Buffer));
  297.         // Receive and print server's reply.
  298.         ReceiveAndPrint(ConnSocket, Buffer, sizeof(Buffer));
  299.     }
  300.     // Tell system we're done sending.
  301.     printf("Done sendingn");
  302.     shutdown(ConnSocket, SD_SEND);
  303.     //
  304.     // Since TCP does not preserve message boundaries, there may still
  305.     // be more data arriving from the server.  So we continue to receive
  306.     // data until the server closes the connection.
  307.     //
  308.     if (SocketType == SOCK_STREAM)
  309.         while(ReceiveAndPrint(ConnSocket, Buffer, sizeof(Buffer)) != 0)
  310.             ;
  311.     closesocket(ConnSocket);
  312.     WSACleanup();
  313.     return 0;
  314. }