LISTEN.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:13k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  2. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  3. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  4. // PARTICULAR PURPOSE.
  5. //
  6. // Copyright (C) 1993-1997  Microsoft Corporation.  All Rights Reserved.
  7. //
  8. //  MODULE:   listen.c
  9. //
  10. //  PURPOSE:   Displays the "Listen" dialog box
  11. //
  12. //  FUNCTIONS:
  13. //    CmdListen          - Displays the "Listen" dialog box.
  14. //    Listen             - Processes messages for "Listen" dialog box.
  15. //    MsgListenInit      - Centers dialog and initializes edit controls.
  16. //    MsgListenConnected - Handles Connected message when socket is connected.
  17. //    MsgListenCommand   - Process WM_COMMAND message sent to the listen box.
  18. //    CmdListenDone      - Free the listen box and related data.
  19. //    CmdListenNow       - Sets up listen on specified socket
  20. //
  21. //  COMMENTS:
  22. //
  23. //
  24. #include <windows.h>            // required for all Windows applications
  25. #include <windowsx.h>
  26. #include <wsipx.h>
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include "globals.h"            // prototypes specific to this application
  30. LRESULT CALLBACK Listen(HWND, UINT, WPARAM, LPARAM);
  31. LRESULT MsgListenInit(HWND, UINT, WPARAM, LPARAM);
  32. LRESULT MsgListenCommand(HWND, UINT, WPARAM, LPARAM);
  33. LRESULT MsgListenConnected(HWND, UINT, WPARAM, LPARAM);
  34. LRESULT CmdListenNow(HWND, WORD, WORD, HWND);
  35. LRESULT CmdListenDone(HWND, WORD, WORD, HWND);
  36. // Listen dialog message table definition.
  37. MSD rgmsdListen[] =
  38. {
  39.     {WM_COMMAND,    MsgListenCommand},
  40.     {WM_INITDIALOG, MsgListenInit},
  41.     {LDM_CONNECTED, MsgListenConnected}
  42. };
  43. MSDI msdiListen =
  44. {
  45.     sizeof(rgmsdListen) / sizeof(MSD),
  46.     rgmsdListen,
  47.     edwpNone
  48. };
  49. // Listen dialog command table definition.
  50. CMD rgcmdListen[] =
  51. {
  52.     {IDOK,     CmdListenNow},
  53.     {IDCANCEL, CmdListenDone}
  54. };
  55. CMDI cmdiListen =
  56. {
  57.     sizeof(rgcmdListen) / sizeof(CMD),
  58.     rgcmdListen,
  59.     edwpNone
  60. };
  61. // Module specific "globals"  Used when a variable needs to be
  62. // accessed in more than one handler function.
  63. HFONT hfontDlg;
  64. //
  65. //  FUNCTION: CmdListen(HWND, WORD, WORD, HWND)
  66. //
  67. //  PURPOSE: Displays the "Listen" dialog box
  68. //
  69. //  PARAMETERS:
  70. //    hwnd      - Window handle
  71. //    wCommand  - IDM_LISTEN          (unused)
  72. //    wNotify   - Notification number (unused)
  73. //    hwndCtrl  - NULL                (unused)
  74. //
  75. //  RETURN VALUE:
  76. //
  77. //    Always returns 0 - Message handled
  78. //
  79. //  COMMENTS:
  80. //    To process the IDM_LISTEN message, call DialogBox() to display the
  81. //    Listen dialog box.
  82. LRESULT CmdListen(HWND hwnd, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  83. {
  84.     HMENU hmenu;
  85.     SetWindowText(hwnd, "IPX Chat Server");     // Change title bar text
  86.     
  87.     // Start Dialog
  88.     if(DialogBox(hInst, "ListenBox", hwnd, (DLGPROC)Listen))
  89.     {
  90.         // Dialog got a connection!  Set Message to indicate
  91.         // when we have data to read, or if the connection is
  92.         // closed on us.
  93.         if (WSAAsyncSelect(sock,
  94.                            hwnd,
  95.                            MW_DATAREADY,
  96.                            FD_READ | FD_CLOSE) == SOCKET_ERROR) 
  97.         {
  98.             MessageBox(hwnd, "WSAAsyncSelect Failed!", NULL, MB_OK);
  99.             CleanUp();
  100.             return 0;
  101.         }
  102.         // Fix menus
  103.         hmenu = GetMenu(hwnd);
  104.         EnableMenuItem(hmenu, IDM_CONNECT, MF_GRAYED);
  105.         EnableMenuItem(hmenu, IDM_LISTEN, MF_GRAYED);
  106.         EnableMenuItem(hmenu, IDM_DISCONNECT, MF_ENABLED);
  107.         return 0;
  108.     }
  109.     // Listen Failed
  110.     SetWindowText(hwnd, szTitle);
  111.     return 0;
  112. }
  113. //
  114. //  FUNCTION: Listen(HWND, UINT, WPARAM, LPARAM)
  115. //
  116. //  PURPOSE:  Processes messages for "Listen" dialog box.
  117. //
  118. //  PARAMETERS:
  119. //    hdlg - window handle of the dialog box
  120. //    wMessage - type of message
  121. //    wparam - message-specific information
  122. //    lparam - message-specific information
  123. //
  124. //  RETURN VALUE:
  125. //    TRUE - message handled
  126. //    FALSE - message not handled
  127. //
  128. //  COMMENTS:
  129. //
  130. //     Gets port information from user and then listens
  131. //
  132. //     Listen when user clicks on the OK button.  Kill Dialog when connection
  133. //     established.
  134. //
  135. LRESULT CALLBACK Listen(HWND hdlg, UINT uMessage, WPARAM wparam, LPARAM lparam)
  136. {
  137.     return DispMessage(&msdiListen, hdlg, uMessage, wparam, lparam);
  138. }
  139. //
  140. //  FUNCTION: MsgListenInit(HWND, UINT, WPARAM, LPARAM)
  141. //
  142. //  PURPOSE: To center dialog and limit size of edit controls and initialize
  143. //
  144. //  PARAMETERS:
  145. //    hdlg - The window handing the message.
  146. //    uMessage - The message number. (unused).
  147. //    wparam - Message specific data (unused).
  148. //    lparam - Message specific data (unused).
  149. //
  150. //  RETURN VALUE:
  151. //    Always returns 0 - message handled.
  152. //
  153. //  COMMENTS:
  154. //    Set size of edit controls for the following
  155. //           Socket   4  chars (2 2-digit hex numbers)
  156. //
  157. LRESULT MsgListenInit(HWND hdlg, UINT uMessage, WPARAM wparam, LPARAM lparam)
  158. {
  159.     // Create a font to use
  160.     hfontDlg = CreateFont(14, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0, 
  161.                           VARIABLE_PITCH | FF_SWISS, "");
  162.     // Center the dialog over the application window
  163.     CenterWindow (hdlg, GetWindow (hdlg, GW_OWNER));
  164.      
  165.     // Initialize Socket Addresses
  166.     SetDlgItemText(hdlg, LD_SOCKET, szListenSocket);
  167.     // Limit input to proper size strings
  168.     SendDlgItemMessage(hdlg, LD_SOCKET, EM_LIMITTEXT, 4, 0);
  169.     return (TRUE);
  170. }
  171. //
  172. //  FUNCTION: MsgListenConnected(HWND, UINT, WPARAM, LPARAM)
  173. //
  174. //  PURPOSE: To handle connected message when socket is connected
  175. //
  176. //  PARAMETERS:
  177. //    hdlg - The window handing the message.
  178. //    uMessage - The message number. (unused).
  179. //    wparam - Message specific data (unused).
  180. //    lparam - Message specific data (unused).
  181. //
  182. //  RETURN VALUE:
  183. //    Always returns 0 - message handled.
  184. //
  185. //  COMMENTS:
  186. //    Performs accept() on incoming socket
  187. //
  188. LRESULT MsgListenConnected(HWND hdlg, UINT uMessage, WPARAM wparam, LPARAM lparam)
  189. {
  190.     char outtext[128];
  191.     SetDlgItemText(hdlg,
  192.                    LD_STATUS,
  193.                    "Client Connected!");
  194.     SetDlgItemText(hdlg,
  195.                    LD_STATUS,
  196.                    "Calling accept()");
  197.     pRemAddr = (PSOCKADDR_IPX)&addr;
  198.     addrlen = sizeof(addr);
  199.     // Accept connection
  200.     if ((sock = accept(SrvSock, (struct sockaddr *)pRemAddr, &addrlen)) == INVALID_SOCKET)
  201.     {
  202.         // accept() failed -- show status and clean up dialog
  203.         sprintf(outtext, "Accept() failed, error %u",WSAGetLastError());
  204.         SetDlgItemText(hdlg,
  205.                        LD_STATUS,
  206.                        outtext);
  207.         closesocket(SrvSock);
  208.         WSACleanup();
  209.         EnableWindow(GetDlgItem(hdlg, IDOK), TRUE);
  210.         EnableWindow(GetDlgItem(hdlg, LD_SOCKET), TRUE);
  211.         SetFocus(GetDlgItem(hdlg, LD_SOCKET));
  212.         return(TRUE);
  213.     }
  214.     // We're connected!
  215.     GetAddrString(pRemAddr, outtext);
  216.     lstrcat(outtext, " connected!");
  217.     SetDlgItemText(hdlg,
  218.                    LD_STATUS,
  219.                    outtext);
  220.           
  221.     EndDialog(hdlg, TRUE);          // Exit the dialog
  222.     DeleteObject (hfontDlg);        // Drop font
  223.     return (TRUE);
  224. }
  225. //
  226. //  FUNCTION: MsgListenCommand(HWND, UINT, WPARAM, LPARAM)
  227. //
  228. //  PURPOSE: Process WM_COMMAND message sent to the Listen box.
  229. //
  230. //  PARAMETERS:
  231. //    hwnd - The window handing the message.
  232. //    uMessage - The message number. (unused).
  233. //    wparam - Message specific data (unused).
  234. //    lparam - Message specific data (unused).
  235. //
  236. //  RETURN VALUE:
  237. //    Always returns 0 - message handled.
  238. //
  239. //  COMMENTS:
  240. //    Uses this DispCommand function defined in wndproc.c combined
  241. //    with the cmdiListen structure defined in this file to handle
  242. //    the command messages for the Listen dialog box.
  243. //
  244. LRESULT MsgListenCommand(HWND   hwnd, 
  245.                         UINT   uMessage, 
  246.                         WPARAM wparam, 
  247.                         LPARAM lparam)
  248. {
  249.     return DispCommand(&cmdiListen, hwnd, wparam, lparam);
  250. }
  251. //
  252. //  FUNCTION: CmdListenDone(HWND, WORD, HWND)
  253. //
  254. //  PURPOSE: Free the Listen box and related data.
  255. //
  256. //  PARAMETERS:
  257. //    hdlg - The window handling the command.
  258. //    wCommand - The command to be handled (unused).
  259. //    wNotify   - Notification number      (unused)
  260. //    hwndCtrl - NULL                      (unused).
  261. //
  262. //  RETURN VALUE:
  263. //    Always returns TRUE.
  264. //
  265. //  COMMENTS:
  266. //    Cleans up sockets then calls EndDialog to finish the dialog session.
  267. //
  268. LRESULT CmdListenDone(HWND hdlg, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  269. {
  270.     closesocket(SrvSock);    // Free any aborted socket resources
  271.     WSACleanup();
  272.     DeleteObject (hfontDlg); // Drop the font
  273.     EndDialog(hdlg, FALSE);  // Exit Dialog -- rtrn false since no connection
  274.     return TRUE;
  275. }
  276. //
  277. //  FUNCTION: CmdListenNow(HWND, WORD, WORD, HWND)
  278. //
  279. //  PURPOSE: Handles ID_OK message and listens on the specified socket
  280. //
  281. //  PARAMETERS:
  282. //    hwnd - The window handling the command.
  283. //    wCommand - The command to be handled (unused).
  284. //    wNotify   - Notification number (unused)
  285. //    hwndCtrl - NULL (unused).
  286. //
  287. //  RETURN VALUE:
  288. //    Always returns TRUE.
  289. //
  290. //  COMMENTS:
  291. //    Shows Listening address on status bar when listen is successful.
  292. //
  293. LRESULT CmdListenNow(HWND hdlg, WORD wCommand, WORD wNotify, HWND hwndCtrl)
  294. {
  295.     char szXferBuffer[5];
  296.     WORD wVersionRequested;
  297.     WSADATA wsaData;
  298.     char outtext[80];
  299.     // Get Socket Address
  300.     GetDlgItemText(hdlg,
  301.          LD_SOCKET,
  302.          szXferBuffer,
  303.          13);
  304.     wVersionRequested = MAKEWORD(1, 1);
  305.     SetDlgItemText(hdlg,
  306.                   LD_STATUS,
  307.                   "Calling WSAStartup");
  308.     // Initializes winsock dll
  309.     if(WSAStartup(wVersionRequested, &wsaData) == SOCKET_ERROR)
  310.     {
  311.         SetDlgItemText(hdlg,
  312.                        LD_STATUS,
  313.                        "WSAStartup failed");
  314.         return (TRUE);
  315.     }
  316.     SetDlgItemText(hdlg,
  317.           LD_STATUS,
  318.           "WSAStartup Succeeded");
  319.     SetDlgItemText(hdlg,
  320.           LD_STATUS,
  321.           "Calling socket()");
  322.     // Allocate socket handle
  323.     SrvSock = socket(AF_IPX,         // IPX Family
  324.                      SOCK_SEQPACKET, // Gives message mode transfers
  325.                      NSPROTO_SPX);   // SPX is connection oriented transport
  326.     if(SrvSock == INVALID_SOCKET) {
  327.         SetDlgItemText(hdlg,
  328.                        LD_STATUS,
  329.                        "ERROR on socket()");
  330.         WSACleanup();
  331.         return(TRUE);
  332.     }
  333.     SetDlgItemText(hdlg,
  334.                    LD_STATUS,
  335.                    "socket() Succeeded");
  336.     // Set up socket address to bind to
  337.     memset(&addr, 0, sizeof(addr));    // Clear address
  338.     pSockAddr = (PSOCKADDR_IPX)&addr;  // Set pointer
  339.     pSockAddr->sa_family = AF_IPX;     // IPX Family
  340.     // Make sure socket number is in network order
  341.     AtoH(szXferBuffer, (char *)&pSockAddr->sa_socket, 2);
  342.     SetDlgItemText(hdlg,
  343.                    LD_STATUS,
  344.                    "Calling bind()");
  345.     // Bind to socket address
  346.     if(bind(SrvSock, 
  347.             (PSOCKADDR) pSockAddr, 
  348.             sizeof(SOCKADDR_IPX)) == SOCKET_ERROR)
  349.     {
  350.         SetDlgItemText(hdlg,
  351.                        LD_STATUS,
  352.                        "Error on bind()");
  353.         closesocket(SrvSock);
  354.         WSACleanup();
  355.         return(TRUE);
  356.     }
  357.     SetDlgItemText(hdlg,
  358.                    LD_STATUS,
  359.                    "bind() Succeeded");
  360.     SetDlgItemText(hdlg,
  361.                    LD_STATUS,
  362.                    "Calling listen()");
  363.     // Set up listen queue - this app only supports one connection so
  364.     // queue length is set to 1.
  365.     if (listen(SrvSock, 1) == SOCKET_ERROR)
  366.     {
  367.         sprintf(outtext, "FAILURE: listen() returned %u", WSAGetLastError());
  368.         SetDlgItemText(hdlg,                       
  369.                        LD_STATUS,
  370.                        outtext);
  371.         closesocket(SrvSock);
  372.         WSACleanup();
  373.         return(TRUE);
  374.     }
  375.     SetDlgItemText(hdlg,
  376.                    LD_STATUS,
  377.                    "listen() succeeded");
  378.     SetDlgItemText(hdlg,
  379.                    LD_STATUS,
  380.                    "Calling WSAAsyncSelect()");
  381.     // Specify message to be posted when client connects
  382.     if(WSAAsyncSelect(SrvSock, 
  383.                       hdlg, 
  384.                       LDM_CONNECTED, 
  385.                       FD_ACCEPT) == SOCKET_ERROR)
  386.     {
  387.         SetDlgItemText(hdlg,
  388.                        LD_STATUS,
  389.                        "WSAAsyncSelect() failed");
  390.         closesocket(SrvSock);
  391.         WSACleanup();
  392.         return(TRUE);
  393.     }
  394.     SetDlgItemText(hdlg,
  395.                    LD_STATUS,
  396.                    "WSAAsyncSelect() succeeded");
  397.     addrlen = sizeof(addr);
  398.     // Get full network.number.socket address
  399.     if(getsockname(SrvSock,&addr,&addrlen) == SOCKET_ERROR)
  400.     {
  401.         lstrcpy(outtext, "ERROR getsocketname()");
  402.     }
  403.     else
  404.     {
  405.         lstrcpy(outtext, "Listening on ");
  406.         GetAddrString((PSOCKADDR_IPX)&addr, outtext + lstrlen(outtext));
  407.     }
  408.     SetDlgItemText(hdlg,
  409.                    LD_STATUS,
  410.                    outtext);
  411.     
  412.     SetFocus(GetDlgItem(hdlg, IDCANCEL));             // Give Cancel Button focus
  413.     EnableWindow(GetDlgItem(hdlg, IDOK), FALSE);      // Grey OK button
  414.     EnableWindow(GetDlgItem(hdlg, LD_SOCKET), FALSE); // Grey Socket Edit control
  415.     return (TRUE);
  416. }