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 / nwlink / dgsend / dgsend.c next >
C/C++ Source or Header  |  1997-10-05  |  10KB  |  424 lines

  1. /****************************************************************************\
  2. *  dgsend.c -- sample program demonstrating NWLink.
  3. *
  4. *       Microsoft Developer Support
  5. *       Copyright (c) 1992-1997 Microsoft Corporation
  6. *
  7. *      This program is a simple example of opening a socket,
  8. *      binding to the socket, and sending a packet repeatedly.
  9. ****************************************************************************/
  10. #include <windows.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <malloc.h>
  15. #include <wsipx.h>
  16. #include <wsnwlink.h>
  17. #include "..\testlib\testlib.h"
  18.  
  19. /*
  20. *   Sockaddr structures 
  21. */
  22.  
  23. SOCKADDR_IPX addr;
  24. SOCKADDR_IPX baddr;
  25. SOCKADDR_IPX saddr;
  26.  
  27. /*
  28. *   Data for sending 
  29. */
  30.  
  31. char send_data[] = "This is an IPX packet from NT";
  32.  
  33. /*
  34. *   Function Prototypes 
  35. */
  36. extern int main(int, char **);
  37. extern int net_init(SOCKET *);
  38. extern int enable_broadcasts(SOCKET);
  39. extern void build_dest_addr(SOCKET, PSOCKADDR_IPX);
  40. extern int dg_send(SOCKET);
  41.  
  42. /****************************************************************************
  43. *
  44. *    FUNCTION:  main( int argc, char **argv )
  45. *
  46. *    PURPOSE:   This is the main entry for the program
  47. *               
  48. *
  49. *    ARGUMENTS:    argc = Number of arguments
  50. *               argv = Array of ptrs to cmd line args
  51. *                
  52. *
  53. *     RETURNS:   Exit code for the program
  54. *                
  55. *\***************************************************************************/
  56. int main(int argc, char **argv)
  57. {
  58.     SOCKET s;
  59.  
  60.     /*
  61.     *   Fill in any default values before checking the command line 
  62.     */
  63.  
  64.     *Remote_Socket_Number = 0x06;
  65.     *(Remote_Socket_Number+1) = 0x00;
  66.     Sleep_Time = 500;
  67.  
  68.     /*
  69.     *   Parse the command line to set up any command line options 
  70.     */
  71.  
  72.     parse_cmd_line(argc, argv);
  73.  
  74.     if (net_init(&s))
  75.         return 1;
  76.  
  77.     if (!No_Broadcast) {
  78.         if (enable_broadcasts(s))
  79.             return 1;
  80.     }
  81.  
  82.     build_dest_addr(s, &saddr);
  83.  
  84.     /*
  85.     *   Send some datagrams 
  86.     */
  87.  
  88.     dg_send(s);
  89.  
  90.     /*
  91.     *   All Done - Close up the socket and exit 
  92.     */
  93.  
  94.     if (verbose)
  95.     printf("Calling closesocket()\n");
  96.  
  97.     closesocket(s);
  98.     return 0;
  99. }
  100.  
  101. /****************************************************************************
  102. *
  103. *    FUNCTION:  net_init( SOCKET *skt )
  104. *
  105. *    PURPOSE:   Initializes the WinSock stuff and sets up our socket.
  106. *               
  107. *
  108. *    ARGUMENTS:    SOCKET * => struct to receive our socket info    
  109. *
  110. *     RETURNS:   0 if ok
  111. *                1 if error
  112. *
  113. *\***************************************************************************/
  114. int net_init(SOCKET *skt)
  115. {
  116.     SOCKET s;
  117.     WSADATA wsdata;
  118.     WORD    wVersionRequested;
  119.  
  120.  
  121.     int rc, addrlen = 16;
  122.  
  123.     if (verbose)
  124.         printf("Calling WSAStartup(), ");
  125.  
  126.     /*
  127.     *   Initialize with the WINSOCK library 
  128.     */
  129.  
  130.     wVersionRequested = MAKEWORD(1,1);
  131.     rc = WSAStartup(wVersionRequested, &wsdata);
  132.  
  133.     if (verbose)
  134.         printf("return = 0x%X (%d)\n", rc, rc);
  135.  
  136.     if (rc) {
  137.         printf("WSAStartup failed: error code = %d\n", rc);
  138.         return 1;
  139.     }
  140.  
  141.     if (verbose) {
  142.         printf("Contents of wsadata struct:\n");
  143.         print_wsa(&wsdata);
  144.     }
  145.  
  146.     /*
  147.     *   Open a DATAGRAM socket with IPX 
  148.     */
  149.  
  150.     if (verbose)
  151.         printf("Calling socket(address family = %d, socket type = %d, protocol = %d)\n", Local_Address_Family, Socket_Type, Protocol);
  152.  
  153.     s = socket(Local_Address_Family, Socket_Type, Protocol);
  154.  
  155.     if (verbose)
  156.     printf("socket() returned 0x%X (%d)\n", s, s);
  157.  
  158.     if (s == INVALID_SOCKET) {
  159.         dos_net_perror("Socket call failed");
  160.         exit(1);
  161.     }
  162.  
  163.     /*
  164.     *   Bind to a socket.  We dont care what socket we bind to,
  165.     *   so we will send down all 0's
  166.     */
  167.  
  168.     addr.sa_family = Local_Address_Family;
  169.  
  170.     memcpy(&addr.sa_netnum, Local_Network_Number, 4);
  171.     memcpy(&addr.sa_nodenum, Local_Node_Number, 6);
  172.     memcpy(&addr.sa_socket, Local_Socket_Number, 2);
  173.  
  174.     if (verbose) {
  175.         printf("calling bind(), local address =\n  ");
  176.         print_saddr(&addr);
  177.     }
  178.  
  179.     rc = bind(s, (const struct sockaddr *) &addr, 16);
  180.  
  181.     if (verbose)
  182.         printf("\nbind() returned 0x%X (%d)\n", rc, rc);
  183.  
  184.     if (rc == SOCKET_ERROR) {
  185.         dos_net_perror("Error binding to socket");
  186.         printf("Socket = 0x%lx\n", s);
  187.         closesocket(s);
  188.         return 1;
  189.     }
  190.  
  191.     /*
  192.     *   Get the address we bound to and print it out 
  193.     */
  194.  
  195.     if (verbose)
  196.         printf("calling getsockname(socket = %d), ", s);
  197.  
  198.     rc = getsockname(s, (struct sockaddr *) &baddr, &addrlen);
  199.  
  200.     if (verbose)
  201.         printf("return = 0x%lX (%d)\n", rc, rc);
  202.  
  203.     if (rc == SOCKET_ERROR) {
  204.         dos_net_perror("Error getting socket name");
  205.         closesocket(s);
  206.         return 1;
  207.     }
  208.  
  209.     /*
  210.     *   Set the packet type for this socket 
  211.     */
  212.  
  213.     if (verbose)
  214.         printf("Calling setsockopt for packet type %d\n", Local_Packet_Type);
  215.  
  216.     rc = setsockopt(s, NSPROTO_IPX, IPX_PTYPE, (const char *) &Local_Packet_Type, 4);
  217.  
  218.     if (rc == SOCKET_ERROR)
  219.         dos_net_perror("setsockopt() call failed");
  220.  
  221.     /*
  222.     *   Print out the network address 
  223.     */
  224.  
  225.     if (verbose) {
  226.         printf("addrlen = %d\n", addrlen);
  227.         print_netaddr(baddr.sa_netnum, "  Bound to address ", "\n");
  228.     }
  229.  
  230.     *skt = s;
  231.  
  232.     return 0;
  233. }
  234.  
  235. /****************************************************************************
  236. *
  237. *    FUNCTION:  enable_broadcasts( SOCKET s )
  238. *
  239. *    PURPOSE:   Sets the socket option to enable broadcast sends on it.
  240. *               
  241. *
  242. *    ARGUMENTS:    SOCKET   socket to enable    
  243. *
  244. *     RETURNS:   0 if ok
  245. *                1 if error
  246. *
  247. *\***************************************************************************/
  248. int enable_broadcasts(SOCKET s)
  249. {
  250.     int rc;
  251.     BOOL optval = TRUE;
  252.  
  253.     /*
  254.     *   Enable sending of broadcasts 
  255.     */
  256.  
  257.     /*
  258.     *    NOTE:  This only needs to be done if you want to SEND
  259.     *           broadcast packets.  Reception of broadcast
  260.     *           packets will happen automatically.
  261.     */
  262.  
  263.     if (verbose)
  264.         printf("Setting socket option to broadcast, ");
  265.     rc = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(int));
  266.     if (verbose)
  267.         printf("return = 0x%X (%d)\n", rc, rc);
  268.  
  269.     if (rc == SOCKET_ERROR) {
  270.         dos_net_perror("Error enabling broadcast address");
  271.         closesocket(s);
  272.         return 1;
  273.     }
  274.  
  275.     return 0;
  276. }
  277.  
  278. /****************************************************************************
  279. *
  280. *    FUNCTION:  build_dest_addr( SOCKET s )
  281. *
  282. *    PURPOSE:   Fills in the destination address fields and sets the packet type.
  283. *               
  284. *
  285. *    ARGUMENTS:    SOCKET       socket to set packet type for
  286. *                PSOCKADDR_NS => address struct to fill in    
  287. *
  288. *     RETURNS:   0 if ok
  289. *                1 if error
  290. *
  291. *\***************************************************************************/
  292. void build_dest_addr(SOCKET s, PSOCKADDR_IPX psaddr)
  293. {
  294.     int rc;
  295.  
  296.     /*
  297.     *   Build the dest. address 
  298.     */
  299.  
  300.     psaddr->sa_family = Remote_Address_Family;
  301.  
  302.     /*
  303.     *   Set dest. network number 
  304.     */
  305.  
  306.     memcpy(&psaddr->sa_netnum, Remote_Network_Number, 4);
  307.  
  308.     /*
  309.     *   Set dest. node address 
  310.     */
  311.  
  312.     memcpy(&psaddr->sa_nodenum, Remote_Node_Number, 6);
  313.  
  314.     /*
  315.     *   Set the dest. socket number 
  316.     */
  317.  
  318.     memcpy(&psaddr->sa_socket, Remote_Socket_Number, 2);
  319.  
  320.  
  321.     /*
  322.     *   Set the packet type for this socket 
  323.     */
  324.  
  325.     if (verbose)
  326.         printf("Calling setsockopt for packet type %d\n", Send_Packet_Type);
  327.  
  328.     rc = setsockopt(s, NSPROTO_IPX, IPX_PTYPE, (const char *) &Send_Packet_Type, sizeof(int));
  329.  
  330.     if (rc == SOCKET_ERROR)
  331.         dos_net_perror("setsockopt() call failed");
  332.  
  333.     return;
  334. }
  335.  
  336. /****************************************************************************
  337. *
  338. *    FUNCTION:  dg_send( SOCKET s )
  339. *
  340. *    PURPOSE:   Receives datagrams.
  341. *
  342. *    ARGUMENTS:    SOCKET socket to transmit on
  343. *
  344. *     RETURNS:   0 if ok
  345. *               1 if error
  346. *
  347. *\***************************************************************************/
  348. int dg_send(SOCKET s)
  349. {
  350.     LPSTR sendbuf;
  351.     int rc, errflag = 0;
  352.     UINT dgrms = 0;
  353.  
  354.     if (verbose)
  355.         printf("allocating %d bytes for send buffer\n", Send_Length);
  356.  
  357.     /*
  358.     *   Set up the data buffer to send 
  359.     */
  360.  
  361.     sendbuf = (LPSTR)malloc(Send_Length);
  362.  
  363.     if (!sendbuf) {
  364.         printf("Error allocating %d bytes for send buffer\n", Send_Length);
  365.         return 1;
  366.     }
  367.  
  368.     /*
  369.     *   Zero the buffer and copy as much of our data to it as possible 
  370.     */
  371.  
  372.     memset(sendbuf, 0, Send_Length);
  373.     strncpy(sendbuf, send_data, Send_Length);
  374.  
  375.     while (1) {
  376.         if (verbose) {
  377.             printf("calling sendto(socket = %d, length = %d),\n", s, Send_Length);
  378.             printf("destination address:\n  ");
  379.             print_saddr(&saddr);
  380.         }
  381.  
  382.         /*
  383.         *   Send a packet to everybody 
  384.         */
  385.  
  386.         rc = sendto(s, sendbuf, Send_Length, 0, (const struct sockaddr *) &saddr, 16);
  387.  
  388.         if (verbose)
  389.         printf("\nsendto() returned %d\n", rc);
  390.  
  391.         if (rc == SOCKET_ERROR) {
  392.             dos_net_perror("Sendto() failed");
  393.             errflag++;
  394.             break;
  395.         }
  396.         else {
  397.             printf("\rSent datagram %d, length = %d bytes", ++dgrms, rc);
  398.             if (verbose)
  399.                 printf("\n");
  400.         }
  401.  
  402.         /*
  403.         *   If we are to send only one, break out 
  404.         */
  405.  
  406.         if (No_Loop)
  407.             break;
  408.  
  409.         /*
  410.         *   Sleep for a little while so we don't bombard the network 
  411.         */
  412.  
  413.         Sleep(Sleep_Time);
  414.     }
  415.  
  416.     if (verbose)
  417.         printf("Freeing send buffer\n");
  418.  
  419.     free(sendbuf);
  420.  
  421.     return errflag;
  422. }
  423.