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 / tp4 / client.c next >
C/C++ Source or Header  |  1997-10-09  |  16KB  |  605 lines

  1. /****************************************************************************\
  2. *  dgrecv.c -- sample program demonstrating NWLink.
  3. *
  4. *       Microsoft Developer Support
  5. *       Copyright 1992 - 1997 Microsoft Corporation
  6. *
  7. *  This program is a simple example of using SPX connect.
  8. *
  9. ****************************************************************************/
  10. #include <windows.h>
  11. #include <winsock.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <malloc.h>
  16. #include "wshisotp.h"
  17.  
  18. typedef struct tag_error_struct{
  19.     int     errnum;
  20.     LPSTR   errstr;
  21. } ERROR_STRUCT;
  22.  
  23. SOCKADDR_TP addr;
  24. SOCKADDR_TP caddr;
  25.  
  26. UCHAR ch = 0;
  27.  
  28. char LocalNetworkAddress[22];
  29. char LocalNetworkAddressLength;
  30. short   LocalTsel;
  31. char RemoteNetworkAddress[22];
  32. char RemoteNetworkAddressLength;
  33. short   RemoteTsel;
  34.  
  35. int     verbose = 1;
  36. int     Socket_Type = SOCK_SEQPACKET;
  37. int     Protocol = ISOPROTO_TP4;
  38. int     Local_Address_Family = AF_ISO;
  39. int     Remote_Address_Family = AF_ISO;
  40. int     Backlog = 1;
  41. int     No_Broadcast = 0;
  42. int     No_Loop = 0;
  43. int     Sleep_Time = 1000;
  44. int     Send_Length = 100;
  45. int     Receive_Length = 200;
  46. int     Local_Packet_Type = 0;
  47.  
  48. #define WSAERRGAP1 28
  49. #define WSAERRGAP2 19
  50.  
  51. char msg_no_error[19] =      "No error occurred!";
  52. char msg_unknown_error[14] = "Unknown error";
  53.  
  54. ERROR_STRUCT errlist[] = {
  55.     {WSAEINTR,           "WSAEINTR - Interrupted"},
  56.     {WSAEBADF,           "WSAEBADF - Bad file number"},
  57.     {WSAEFAULT,          "WSAEFAULT - Bad address"},
  58.     {WSAEINVAL,          "WSAEINVAL - Invalid argument"},
  59.     {WSAEMFILE,          "WSAEMFILE - Too many open files"},
  60.  
  61. /*
  62. *    Windows Sockets definitions of regular Berkeley error constants
  63. */
  64.  
  65.     {WSAEWOULDBLOCK,     "WSAEWOULDBLOCK - Socket marked as non-blocking"},
  66.     {WSAEINPROGRESS,     "WSAEINPROGRESS - Blocking call in progress"},
  67.     {WSAEALREADY,        "WSAEALREADY - Command already completed"},
  68.     {WSAENOTSOCK,        "WSAENOTSOCK - Descriptor is not a socket"},
  69.     {WSAEDESTADDRREQ,    "WSAEDESTADDRREQ - Destination address required"},
  70.     {WSAEMSGSIZE,        "WSAEMSGSIZE - Data size too large"},
  71.     {WSAEPROTOTYPE,      "WSAEPROTOTYPE - Protocol is of wrong type for this socket"},
  72.     {WSAENOPROTOOPT,     "WSAENOPROTOOPT - Protocol option not supported for this socket type"},
  73.     {WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT - Protocol is not supported"},
  74.     {WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT - Socket type not supported by this address family"},
  75.     {WSAEOPNOTSUPP,      "WSAEOPNOTSUPP - Option not supported"},
  76.     {WSAEPFNOSUPPORT,    "WSAEPFNOSUPPORT - "},
  77.     {WSAEAFNOSUPPORT,    "WSAEAFNOSUPPORT - Address family not supported by this protocol"},
  78.     {WSAEADDRINUSE,      "WSAEADDRINUSE - Address is in use"},
  79.     {WSAEADDRNOTAVAIL,   "WSAEADDRNOTAVAIL - Address not available from local machine"},
  80.     {WSAENETDOWN,        "WSAENETDOWN - Network subsystem is down"},
  81.     {WSAENETUNREACH,     "WSAENETUNREACH - Network cannot be reached"},
  82.     {WSAENETRESET,       "WSAENETRESET - Connection has been dropped"},
  83.     {WSAECONNABORTED,    "WSAECONNABORTED - "},
  84.     {WSAECONNRESET,      "WSAECONNRESET - "},
  85.     {WSAENOBUFS,         "WSAENOBUFS - No buffer space available"},
  86.     {WSAEISCONN,         "WSAEISCONN - Socket is already connected"},
  87.     {WSAENOTCONN,        "WSAENOTCONN - Socket is not connected"},
  88.     {WSAESHUTDOWN,       "WSAESHUTDOWN - Socket has been shut down"},
  89.     {WSAETOOMANYREFS,    "WSAETOOMANYREFS - "},
  90.     {WSAETIMEDOUT,       "WSAETIMEDOUT - Command timed out"},
  91.     {WSAECONNREFUSED,    "WSAECONNREFUSED - Connection refused"},
  92.     {WSAELOOP,           "WSAELOOP - "},
  93.     {WSAENAMETOOLONG,    "WSAENAMETOOLONG - "},
  94.     {WSAEHOSTDOWN,       "WSAEHOSTDOWN - "},
  95.     {WSAEHOSTUNREACH,    "WSAEHOSTUNREACH - "},
  96.     {WSAENOTEMPTY,       "WSAENOTEMPTY - "},
  97.     {WSAEPROCLIM,        "WSAEPROCLIM - "},
  98.     {WSAEUSERS,          "WSAEUSERS - "},
  99.     {WSAEDQUOT,          "WSAEDQUOT - "},
  100.     {WSAESTALE,          "WSAESTALE - "},
  101.     {WSAEREMOTE,         "WSAEREMOTE - "},
  102.  
  103. /*
  104. *    Extended Windows Sockets error constant definitions
  105. */
  106.  
  107.     {WSASYSNOTREADY,     "WSASYSNOTREADY - Network subsystem not ready"},
  108.     {WSAVERNOTSUPPORTED, "WSAVERNOTSUPPORTED - Version not supported"},
  109.     {WSANOTINITIALISED,  "WSANOTINITIALISED - WSAStartup() has not been successfully called"},
  110.  
  111. /*
  112. *    Other error constants.
  113. */
  114.  
  115.     {WSAHOST_NOT_FOUND,  "WSAHOST_NOT_FOUND - Host not found"},
  116.     {WSATRY_AGAIN,       "WSATRY_AGAIN - Host not found or SERVERFAIL"},
  117.     {WSANO_RECOVERY,     "WSANO_RECOVERY - Non-recoverable error"},
  118.     {WSANO_DATA,         "WSANO_DATA - (or WSANO_ADDRESS) - No data record of requested type"},
  119.     {-1,                 NULL}
  120. };
  121.  
  122. /*
  123. *   Function Prototypes
  124. */
  125.  
  126. extern int main(int, char **);
  127. extern int net_init(SOCKET *);
  128. extern int make_connection(SOCKET);
  129. extern int do_send_receive(SOCKET);
  130. extern void dos_net_perror(LPSTR );
  131. extern LPCSTR dos_net_strerror(LPSTR );
  132. extern LPCSTR get_error_text(int );
  133.  
  134. /****************************************************************************
  135. *
  136. *    FUNCTION:  main( int argc, char **argv )
  137. *
  138. *    PURPOSE:   This is the main entry for the program
  139. *
  140. *
  141. *    ARGUMENTS: argc = Number of arguments
  142. *               argv = Array of ptrs to cmd line args
  143. *
  144. *
  145. *        RETURNS:   Exit code for the program
  146. *
  147. *\***************************************************************************/
  148. int main(int argc, char **argv)
  149. {
  150.     SOCKET s;
  151.  
  152.    /*
  153.    ** Read Local & Remote Transport Address fields from user
  154.    */
  155.    printf("LocalNetworkAddress(max. 20 chars) : ");
  156.    scanf("%s", &LocalNetworkAddress[0]);
  157.    printf("LocalTsel : ");
  158.    scanf("%d", &LocalTsel);
  159.    LocalNetworkAddressLength = strlen(LocalNetworkAddress) ;
  160.  
  161.    printf("RemoteNetworkAddress(max. 20 chars) : ");
  162.    scanf("%s", &RemoteNetworkAddress[0]);
  163.    printf("RemoteTsel : ");
  164.    scanf("%d", &RemoteTsel);
  165.    RemoteNetworkAddressLength = strlen(RemoteNetworkAddress) ;
  166.  
  167. printf("local Tsel(%d) Net_length(%d) Net(%s)\n",
  168.         LocalTsel, LocalNetworkAddressLength, LocalNetworkAddress);
  169. printf("Remote Tsel(%d) Net_length(%d) Net(%s)\n",
  170.         RemoteTsel, RemoteNetworkAddressLength, RemoteNetworkAddress);
  171.  
  172.  
  173.     /*
  174.     *   Initialize the network and set up the socket
  175.     */
  176.  
  177.     if (net_init(&s))
  178.         return 1;
  179.  
  180.     /*
  181.     *   Try to connect to our server
  182.     */
  183.  
  184.     if (make_connection(s))
  185.         return 1;
  186.  
  187.     /*
  188.     *   Send/receive data to/from server
  189.     */
  190.  
  191.     do_send_receive(s);
  192.  
  193.     /*
  194.     *   All done - close up
  195.     */
  196.  
  197.     if (verbose)
  198.         printf("calling closesocket(socket = %d)\n", s);
  199.  
  200.     closesocket(s);
  201.     return 0;
  202. }
  203.  
  204. /****************************************************************************
  205. *
  206. *    FUNCTION:  net_init( SOCKET *skt )
  207. *
  208. *    PURPOSE:   Initializes the WinSock stuff and sets up our socket.
  209. *
  210. *
  211. *    ARGUMENTS: SOCKET * => struct to fill in with opened socket.
  212. *
  213. *        RETURNS:   0 if ok
  214. *                               1 if error
  215. *
  216. *\***************************************************************************/
  217. int net_init(SOCKET *skt)
  218. {
  219.     SOCKET s;
  220.     int rc, addrlen;
  221.     int reuse = 1;
  222.     WSADATA wsdata;
  223.     WORD    wVersionRequested;
  224.  
  225.     wVersionRequested = MAKEWORD(1,1);
  226.  
  227.  
  228.     /*
  229.     *   Register with the socket library
  230.     */
  231.  
  232.     rc = WSAStartup(wVersionRequested, &wsdata);
  233.  
  234.     if (verbose)
  235.         printf("WSAStartup returned 0x%X\n", rc);
  236.  
  237.     if (rc) {
  238.         printf("WSAStartup failed: error = %d\n", rc);
  239.         return 1;
  240.     }
  241.  
  242.  
  243.     /*
  244.     *   Open a STREAMING socket
  245.     */
  246.  
  247.     s = socket(Local_Address_Family, Socket_Type, Protocol);
  248.  
  249.     if (verbose)
  250.         printf("socket() returned 0x%X (%d)\n", s, s);
  251.  
  252.     if (s == INVALID_SOCKET) {
  253.         printf("socket call failed");
  254.         return 1;
  255.     }
  256.  
  257.     /*
  258.     *   Bind to any address
  259.     */
  260.  
  261.     ISO_SET_TP_ADDR(&addr, &LocalTsel, sizeof(LocalTsel),
  262.                         LocalNetworkAddress, LocalNetworkAddressLength);
  263.  
  264.     rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char FAR *)&reuse, sizeof(int));
  265.     if (rc == SOCKET_ERROR) {
  266.         dos_net_perror("setsockopt call failed");
  267.         return 1;
  268.     }
  269.  
  270.     rc = bind(s, (const struct sockaddr *)&addr, sizeof(SOCKADDR_TP));
  271.  
  272.     if (verbose)
  273.         printf("bind() returned 0x%X\n", rc);
  274.  
  275.     if (rc == SOCKET_ERROR) {
  276.         dos_net_perror("bind call failed");
  277.         return 1;
  278.     }
  279.  
  280.     if (verbose)
  281.         printf("calling getsockname(socket = %d)\n", s);
  282.  
  283.     addrlen = sizeof(SOCKADDR_TP);
  284.     rc = getsockname(s, (struct sockaddr *) &addr, &addrlen);
  285.  
  286.     if (verbose)
  287.         printf("getsockname() returned 0x%X\n", rc);
  288.  
  289.     if (rc == SOCKET_ERROR) {
  290.         printf("Error binding to socket");
  291.         closesocket(s);
  292.         return 1;
  293.     }
  294. /*
  295.     if (verbose) {
  296.         printf("addrlen = %d\n", addrlen);
  297.         print_netaddr(addr.sa_netnum, "Bound address = ", "\n");
  298.     }
  299. */
  300.  
  301.     /*
  302.     *   Build the address of the node to connect to
  303.     */
  304. ISO_SET_TP_ADDR(&caddr, &RemoteTsel, sizeof(RemoteTsel),
  305.                         RemoteNetworkAddress, RemoteNetworkAddressLength);
  306.  
  307. /*
  308.     caddr.sa_family = Remote_Address_Family;
  309.     caddr.addr_type = HIERARCHICAL;
  310.     caddr.taddr_len = RemoteNetworkAddressLength + RemoteTselLength;
  311.     caddr.tsel_len = RemoteTselLength;
  312.     memcpy(&caddr.addr, RemoteTsel, RemoteTselLength);
  313.     memcpy(&caddr.addr[RemoteTselLength],
  314.                 RemoteNetworkAddress, RemoteNetworkAddressLength);
  315. */
  316.  
  317.     /*
  318.     *   Set up socket for return
  319.     */
  320.  
  321.     *skt = s;
  322.  
  323.     return 0;
  324. }
  325.  
  326. /****************************************************************************
  327. *
  328. *    FUNCTION:  make_connection( SOCKET s )
  329. *
  330. *    PURPOSE:   Establishes a connection with our server.
  331. *
  332. *    ARGUMENTS: SOCKET socket to use for connection
  333. *
  334. *        RETURNS:   0 if ok
  335. *                               1 if error
  336. *
  337. *\***************************************************************************/
  338. int make_connection(SOCKET s)
  339. {
  340.     int rc, addrlen;
  341.  
  342.     /*
  343.     *   Connect
  344.     */
  345.  
  346.     if (verbose)
  347.         printf("calling connect(socket = %d)\n", s);
  348.  
  349.     rc = connect(s, (const struct sockaddr FAR *)&caddr, sizeof(SOCKADDR_TP));
  350.  
  351.     if (verbose)
  352.         printf("connect() returned 0x%X\n", rc);
  353.  
  354.     if (rc == SOCKET_ERROR) {
  355.         dos_net_perror("connect call failed");
  356.         return 1;
  357.     }
  358.  
  359.     printf("Connect OK\n");
  360.  
  361.     /*
  362.     *   Print out address we connected to
  363.     */
  364.  
  365.     if (verbose)
  366.         printf("calling getpeername(socket = %d)\n", s);
  367.  
  368.     addrlen = sizeof(SOCKADDR_TP);
  369.     rc = getpeername(s, (struct sockaddr *) &caddr, &addrlen);
  370.  
  371.     if (verbose)
  372.         printf("getpeername() returned 0x%X\n", rc);
  373. /*
  374.     if (verbose) {
  375.         printf("addrlen = %d\n", addrlen);
  376.         print_netaddr(caddr.sa_netnum, "Remote Address = ", "\n");
  377.     }
  378. */
  379.  
  380.     return 0;
  381. }
  382. /****************************************************************************
  383. *
  384. *    FUNCTION:  do_send_receive( SOCKET *s )
  385. *
  386. *    PURPOSE:   Alternately sends/receives data to/from the server.
  387. *
  388. *    ARGUMENTS: SOCKET socket to transmit on
  389. *
  390. *        RETURNS:   0 if ok
  391. *                               1 if error
  392. *
  393. *\***************************************************************************/
  394. int do_send_receive(SOCKET s)
  395. {
  396.     int rc, errflag = 0;
  397.     int sndpkts = 0, rcvpkts = 0;
  398.     LPSTR sendbuf;
  399.  
  400.     /*
  401.     *   Allocate a send buffer
  402.     */
  403.  
  404.     if (verbose)
  405.         printf("Allocating %d bytes for send buffer \n");
  406.  
  407.     sendbuf = malloc(Send_Length);
  408.  
  409.     if (!sendbuf) {
  410.         printf("Error allocating %d bytes for send buffer\n");
  411.         return 1;
  412.     }
  413.  
  414.     /*
  415.     *   Send data and recv it back
  416.     */
  417.  
  418.     while (1) {
  419.  
  420.         /*
  421.         *   Fill the buffer with our current character
  422.         */
  423.  
  424.         memset(sendbuf, ch, Send_Length);
  425.  
  426.         /*
  427.         *   Send data
  428.         */
  429.  
  430.         if (verbose)
  431.             printf("calling send(socket = %d, length = %d)\n", s, Send_Length);
  432.  
  433.         rc = send(s, sendbuf, Send_Length, 0);
  434.  
  435.         if (verbose)
  436.             printf("send() returned 0x%X\n", rc);
  437.  
  438.         if (rc == SOCKET_ERROR) {
  439.             printf("\nsend() call failed");
  440.             errflag++;
  441.             break;
  442.         }
  443.  
  444.         if (verbose)
  445.             printf("Sent packet %d: sent %d bytes\n", sndpkts++, rc);
  446.         else
  447.             printf("\rSent packet %d: sent %d bytes... ", sndpkts++, rc);
  448.  
  449.         /*
  450.         *   Receive the data back
  451.         */
  452. /*
  453.         if (verbose)
  454.             printf("calling recv(socket = %d, length = %d)\n", s, Send_Length);
  455.  
  456.         rc = recv(s, sendbuf, Send_Length, 0);
  457.  
  458.         if (verbose)
  459.             printf("recv() returned %d\n", rc);
  460.  
  461.         if (rc == SOCKET_ERROR) {
  462.             printf("\nrecv() call failed");
  463.             errflag++;
  464.             break;
  465.         }
  466.  
  467.         if (!rc) {
  468.             printf("connection has been lost\n");
  469.             break;
  470.         }
  471.  
  472.         printf("Received %d bytes", rc);
  473. */
  474.         if (verbose)
  475.             printf("\n");
  476.  
  477.         /*
  478.         *   See if our buffer has the same data in it
  479.         */
  480.  
  481.         rc = mem_check(sendbuf, ch++, Send_Length);
  482.  
  483.         if (rc)
  484.             printf("Data compare error: packet = %d, offset = %d\n", (sndpkts-1), rc);
  485.         else if (verbose)
  486.             printf("Data compares okay\n");
  487.  
  488.         /*
  489.         *   If we are to send just 1, break out
  490.         */
  491.  
  492.         if (No_Loop)
  493.             break;
  494.  
  495.         /*
  496.         *   Pause a little while (don't trash the network)
  497.         Sleep(Sleep_Time);
  498.         */
  499.  
  500.     }
  501.  
  502.     if (verbose)
  503.         printf("\nFreeing send buffer\n");
  504.  
  505.     free(sendbuf);
  506.  
  507.     return errflag;
  508. }
  509.  
  510.  
  511. /****************************************************************************
  512. *
  513. *    FUNCTION:  mem_check( LPSTR p, UCHAR ch, int len)
  514. *
  515. *    PURPOSE:   Makes sure that a buffer is filled with only the character
  516. *                   specified.
  517. *
  518. *    ARGUMENTS: LPSTR   => buffer to scan
  519. *               char    character to check for
  520. *               int     length of buffer to check
  521. *
  522. *        RETURNS:   0 if buffer has only the specified character
  523. *                               offset to non-matching character if found
  524. *
  525. ************************************************************************/
  526. int mem_check(LPSTR p, UCHAR ch, int len)
  527. {
  528.     int buflen;
  529.  
  530.     buflen = len;
  531.  
  532.     while (len--) {
  533.         if ((UCHAR)*p++ != ch) {
  534.             return (buflen - len);
  535.         }
  536.     }
  537.  
  538.     return 0;
  539. }
  540.  
  541. void dos_net_perror(LPSTR p)
  542. {
  543.     printf(dos_net_strerror(p));
  544.     printf("\n");
  545.  
  546.     return;
  547. }
  548.  
  549.  
  550.  
  551. LPCSTR dos_net_strerror(LPSTR p)
  552. {
  553.     int error = 0;
  554.     static char return_string[256];
  555.  
  556.     /*
  557.     *   Get the error number from the system
  558.     */
  559.  
  560.     error = h_errno;
  561.  
  562.     /*
  563.     *   Build the string to return
  564.     */
  565.  
  566.     sprintf(return_string, "%s :(%d)%s", p, error, get_error_text(error));
  567.  
  568.     return (LPSTR)return_string;
  569. }
  570.  
  571. LPCSTR get_error_text(int error)
  572. {
  573.     int search = 0;
  574.  
  575.  
  576.     /*
  577.     *   No error
  578.     */
  579.  
  580.     if (!error)
  581.         return (LPCSTR)msg_no_error;
  582.  
  583.     /*
  584.     *   Search through our array of error number / string pairs
  585.     *   until we find a matching error number or get to the end
  586.     *   of our list.  If we found a matching error number,
  587.     *   return a LPSTR to the corresponding string.
  588.     */
  589.  
  590.     while (errlist[search].errstr) {
  591.         if (error == errlist[search].errnum)
  592.             return errlist[search].errstr;
  593.         search++;
  594.     }
  595.  
  596.     /*
  597.     * If we didn't have the error in our list, return unkown
  598.     */
  599.  
  600.     return (LPCSTR)msg_unknown_error;
  601. }
  602.  
  603.  
  604.  
  605.