2012-11-22 36 views
1

我正在使用WM_SOCKET。服務器和客戶端運行良好。但是,如果我關閉客戶端並重新打開它FD_READ不響應只FD_CLOSE和FD_ACCEPT工作正常。請人幫我...WM_SOCKET ... FD_READ沒有響應

服務器代碼:

#include <winsock2.h> 
#include <windows.h> 

#pragma comment(lib,"ws2_32.lib") 

#define IDC_EDIT_IN  101 
#define IDC_EDIT_OUT  102 
#define IDC_MAIN_BUTTON 103 
#define WM_SOCKET  104 

int nPort=5555; 

HWND hEditIn=NULL; 
HWND hEditOut=NULL; 
SOCKET Socket=NULL; 
char szHistory[10000]; 
sockaddr sockAddrClient; 

LRESULT CALLBACK WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam); 

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nShowCmd) 
{ 
    WNDCLASSEX wClass; 
    ZeroMemory(&wClass,sizeof(WNDCLASSEX)); 
    wClass.cbClsExtra=NULL; 
    wClass.cbSize=sizeof(WNDCLASSEX); 
    wClass.cbWndExtra=NULL; 
    wClass.hbrBackground=(HBRUSH)COLOR_WINDOW; 
    wClass.hCursor=LoadCursor(NULL,IDC_ARROW); 
    wClass.hIcon=NULL; 
    wClass.hIconSm=NULL; 
    wClass.hInstance=hInst; 
    wClass.lpfnWndProc=(WNDPROC)WinProc; 
    wClass.lpszClassName="Window Class"; 
    wClass.lpszMenuName=NULL; 
    wClass.style=CS_HREDRAW|CS_VREDRAW; 

    if(!RegisterClassEx(&wClass)) 
    { 
     int nResult=GetLastError(); 
     MessageBox(NULL, 
      "Window class creation failed\r\nError code:", 
      "Window Class Failed", 
      MB_ICONERROR); 
    } 

    HWND hWnd=CreateWindowEx(NULL, "Window Class", "Winsock Async Server", 
      WS_OVERLAPPEDWINDOW, 200, 200, 640, 480, NULL, NULL, hInst, 
      NULL); 

    if(!hWnd) 
    { 
     int nResult=GetLastError(); 

     MessageBox(NULL, 
      "Window creation failed\r\nError code:", 
      "Window Creation Failed", 
      MB_ICONERROR); 
    } 

    ShowWindow(hWnd,nShowCmd); 

    MSG msg; 
    ZeroMemory(&msg,sizeof(MSG)); 

    while(GetMessage(&msg,NULL,0,0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    return 0; 
} 

LRESULT CALLBACK WinProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) 
{ 
    switch(msg) 
    { 
     case WM_COMMAND: 
      switch(LOWORD(wParam)) 
      { 
       case IDC_MAIN_BUTTON: 
       { 
        char szBuffer[1024]; 
        ZeroMemory(szBuffer,sizeof(szBuffer)); 

        SendMessage(hEditOut, 
         WM_GETTEXT, 
         sizeof(szBuffer), 
         reinterpret_cast<LPARAM>(szBuffer)); 

        send(Socket,szBuffer,strlen(szBuffer),0); 

        SendMessage(hEditOut,WM_SETTEXT,NULL,(LPARAM)""); 
       } 
       break; 
      } 
      break; 
     case WM_CREATE: 
     { 
      ZeroMemory(szHistory,sizeof(szHistory)); 

      // Create incoming message box 
      hEditIn=CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "",     WS_CHILD|WS_VISIBLE|ES_MULTILINE|ES_AUTOVSCROLL|ES_AUTOHSCROLL, 
       50, 120, 400, 200, hWnd, (HMENU)IDC_EDIT_IN, 
       GetModuleHandle(NULL), 
       NULL); 
      if(!hEditIn) 
      { 
       MessageBox(hWnd, 
        "Could not create incoming edit box.", 
        "Error", 
        MB_OK|MB_ICONERROR); 
      } 
      HGDIOBJ hfDefault=GetStockObject(DEFAULT_GUI_FONT); 
      SendMessage(hEditIn, 
        WM_SETFONT, 
        (WPARAM)hfDefault, 
        MAKELPARAM(FALSE,0)); 
      SendMessage(hEditIn, 
        WM_SETTEXT, 
        NULL, 
        (LPARAM)"Waiting for client to connect..."); 

      // Create outgoing message box 
      hEditOut=CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", 
         "", WS_CHILD|WS_VISIBLE|ES_MULTILINE| 
         ES_AUTOVSCROLL|ES_AUTOHSCROLL, 
         50, 50, 400, 60, hWnd, 
         (HMENU)IDC_EDIT_IN, 
         GetModuleHandle(NULL), 
         NULL); 
      if(!hEditOut) 
      { 
       MessageBox(hWnd, 
        "Could not create outgoing edit box.", 
        "Error", 
        MB_OK|MB_ICONERROR); 
      } 

      SendMessage(hEditOut, 
        WM_SETFONT, 
        (WPARAM)hfDefault, 
        MAKELPARAM(FALSE,0)); 
      SendMessage(hEditOut, 
        WM_SETTEXT, 
        NULL, 
        (LPARAM)"Type message here..."); 

      // Create a push button 
      HWND hWndButton=CreateWindow( "BUTTON", 
         "Send", 
         WS_TABSTOP|WS_VISIBLE| 
         WS_CHILD|BS_DEFPUSHBUTTON, 
         50, 330, 75, 23, 
         hWnd, (HMENU)IDC_MAIN_BUTTON, 
         GetModuleHandle(NULL), 
         NULL); 

      SendMessage(hWndButton, 
       WM_SETFONT, 
       (WPARAM)hfDefault, 
       MAKELPARAM(FALSE,0)); 

      WSADATA WsaDat; 
      int nResult=WSAStartup(MAKEWORD(2,2),&WsaDat); 
      if(nResult!=0) 
      { 
       MessageBox(hWnd, 
        "Winsock initialization failed", 
        "Critical Error", 
        MB_ICONERROR); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 

      Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
      if(Socket==INVALID_SOCKET) 
      { 
       MessageBox(hWnd, 
        "Socket creation failed", 
        "Critical Error", 
        MB_ICONERROR); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 

      SOCKADDR_IN SockAddr; 
      SockAddr.sin_port=htons(nPort); 
      SockAddr.sin_family=AF_INET; 
      SockAddr.sin_addr.s_addr=htonl(INADDR_ANY); 

      if(bind(Socket,(LPSOCKADDR)&SockAddr,sizeof(SockAddr))==SOCKET_ERROR) 
      { 
       MessageBox(hWnd,"Unable to bind socket","Error",MB_OK); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 

      nResult=WSAAsyncSelect(Socket, 
        hWnd, 
        WM_SOCKET, 
        (FD_CLOSE|FD_ACCEPT|FD_READ)); 
      if(nResult) 
      { 
       MessageBox(hWnd, 
        "WSAAsyncSelect failed", 
        "Critical Error", 
        MB_ICONERROR); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 

      if(listen(Socket,(1))==SOCKET_ERROR) 
      { 
       MessageBox(hWnd, 
        "Unable to listen!", 
        "Error", 
        MB_OK); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 
     } 
     break; 

     case WM_DESTROY: 
     { 
      PostQuitMessage(0); 
      shutdown(Socket,SD_BOTH); 
      closesocket(Socket); 
      WSACleanup(); 
      return 0; 
     } 
     break; 

     case WM_SOCKET: 
     { 
      switch(WSAGETSELECTEVENT(lParam)) 
      { 
       case FD_READ: 
       { 
        char szIncoming[1024]; 
        ZeroMemory(szIncoming,sizeof(szIncoming)); 

        int inDataLength=recv(Socket, 
         (char*)szIncoming, 
         sizeof(szIncoming)/sizeof(szIncoming[0]), 
         0); 

        strncat(szHistory,szIncoming,inDataLength); 
        strcat(szHistory,"\r\n"); 

        SendMessage(hEditIn, 
         WM_SETTEXT, 
         sizeof(szIncoming)-1, 
         reinterpret_cast<LPARAM>(&szHistory)); 
       } 
       break; 

       case FD_CLOSE: 
       { 
        MessageBox(hWnd, 
         "Client closed connection", 
         "Connection closed!", 
         MB_ICONINFORMATION|MB_OK);       } 
       break; 

       case FD_ACCEPT: 
       { 
        int size=sizeof(sockaddr); 
        Socket=accept(wParam,&sockAddrClient,&size);     
        if (Socket==INVALID_SOCKET) 
        { 
         int nret = WSAGetLastError(); 
         WSACleanup(); 
        } 
        SendMessage(hEditIn, 
         WM_SETTEXT, 
         NULL, 
         (LPARAM)"Client connected!"); 
       } 
       break; 
       } 
      } 
     } 

    return DefWindowProc(hWnd,msg,wParam,lParam); 
} 

客戶端代碼:

#include <winsock2.h> 
#include <windows.h> 

#pragma comment(lib,"ws2_32.lib") 

#define IDC_EDIT_IN  101 
#define IDC_EDIT_OUT  102 
#define IDC_MAIN_BUTTON  103 
#define WM_SOCKET  104 

char *szServer="localhost"; 
int nPort=5555; 

HWND hEditIn=NULL; 
HWND hEditOut=NULL; 
SOCKET Socket=NULL; 
char szHistory[10000]; 

LRESULT CALLBACK WinProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam); 

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR lpCmdLine,int nShowCmd) 
{ 
    WNDCLASSEX wClass; 
    ZeroMemory(&wClass,sizeof(WNDCLASSEX)); 
    wClass.cbClsExtra=NULL; 
    wClass.cbSize=sizeof(WNDCLASSEX); 
    wClass.cbWndExtra=NULL; 
    wClass.hbrBackground=(HBRUSH)COLOR_WINDOW; 
    wClass.hCursor=LoadCursor(NULL,IDC_ARROW); 
    wClass.hIcon=NULL; 
    wClass.hIconSm=NULL; 
    wClass.hInstance=hInst; 
    wClass.lpfnWndProc=(WNDPROC)WinProc; 
    wClass.lpszClassName="Window Class"; 
    wClass.lpszMenuName=NULL; 
    wClass.style=CS_HREDRAW|CS_VREDRAW; 

    if(!RegisterClassEx(&wClass)) 
    { 
     int nResult=GetLastError(); 
     MessageBox(NULL, 
      "Window class creation failed\r\nError code:", 
      "Window Class Failed", 
      MB_ICONERROR); 
    } 

    HWND hWnd=CreateWindowEx(NULL, 
      "Window Class", 
      "Windows Async Client", 
      WS_OVERLAPPEDWINDOW, 
      200, 
      200, 
      640, 
      480, 
      NULL, 
      NULL, 
      hInst, 
      NULL); 

    if(!hWnd) 
    { 
     int nResult=GetLastError(); 

     MessageBox(NULL, 
      "Window creation failed\r\nError code:", 
      "Window Creation Failed", 
      MB_ICONERROR); 
    } 

    ShowWindow(hWnd,nShowCmd); 

    MSG msg; 
    ZeroMemory(&msg,sizeof(MSG)); 

    while(GetMessage(&msg,NULL,0,0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    return 0; 
} 

LRESULT CALLBACK WinProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) 
{ 
    switch(msg) 
    { 
     case WM_CREATE: 
     { 
      ZeroMemory(szHistory,sizeof(szHistory)); 

      // Create incoming message box 
      hEditIn=CreateWindowEx(WS_EX_CLIENTEDGE, 
       "EDIT", 
       "", 
       WS_CHILD|WS_VISIBLE|ES_MULTILINE| 
       ES_AUTOVSCROLL|ES_AUTOHSCROLL, 
       50, 
       120, 
       400, 
       200, 
       hWnd, 
       (HMENU)IDC_EDIT_IN, 
       GetModuleHandle(NULL), 
       NULL); 
      if(!hEditIn) 
      { 
       MessageBox(hWnd, 
        "Could not create incoming edit box.", 
        "Error", 
        MB_OK|MB_ICONERROR); 
      } 
      HGDIOBJ hfDefault=GetStockObject(DEFAULT_GUI_FONT); 
      SendMessage(hEditIn, 
       WM_SETFONT, 
       (WPARAM)hfDefault, 
       MAKELPARAM(FALSE,0)); 
      SendMessage(hEditIn, 
       WM_SETTEXT, 
       NULL, 
       (LPARAM)"Attempting to connect to server..."); 

      // Create outgoing message box 
      hEditOut=CreateWindowEx(WS_EX_CLIENTEDGE, 
         "EDIT", 
         "", 
         WS_CHILD|WS_VISIBLE|ES_MULTILINE| 
         ES_AUTOVSCROLL|ES_AUTOHSCROLL, 
         50, 
         50, 
         400, 
         60, 
         hWnd, 
         (HMENU)IDC_EDIT_IN, 
         GetModuleHandle(NULL), 
         NULL); 
      if(!hEditOut) 
      { 
       MessageBox(hWnd, 
        "Could not create outgoing edit box.", 
        "Error", 
        MB_OK|MB_ICONERROR); 
      } 

      SendMessage(hEditOut, 
       WM_SETFONT,(WPARAM)hfDefault, 
       MAKELPARAM(FALSE,0)); 
      SendMessage(hEditOut, 
       WM_SETTEXT, 
       NULL, 
       (LPARAM)"Type message here..."); 

      // Create a push button 
      HWND hWndButton=CreateWindow( 
         "BUTTON", 
         "Send", 
         WS_TABSTOP|WS_VISIBLE| 
         WS_CHILD|BS_DEFPUSHBUTTON, 
         50, 
         330, 
         75, 
         23, 
         hWnd, 
         (HMENU)IDC_MAIN_BUTTON, 
         GetModuleHandle(NULL), 
         NULL); 

      SendMessage(hWndButton, 
       WM_SETFONT, 
       (WPARAM)hfDefault, 
       MAKELPARAM(FALSE,0)); 

      // Set up Winsock 
      WSADATA WsaDat; 
      int nResult=WSAStartup(MAKEWORD(2,2),&WsaDat); 
      if(nResult!=0) 
      { 
       MessageBox(hWnd, 
        "Winsock initialization failed", 
        "Critical Error", 
        MB_ICONERROR); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 

      Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
      if(Socket==INVALID_SOCKET) 
      { 
       MessageBox(hWnd, 
        "Socket creation failed", 
        "Critical Error", 
        MB_ICONERROR); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 

      nResult=WSAAsyncSelect(Socket,hWnd,WM_SOCKET,(FD_CLOSE|FD_READ)); 
      if(nResult) 
      { 
       MessageBox(hWnd, 
        "WSAAsyncSelect failed", 
        "Critical Error", 
        MB_ICONERROR); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 

      // Resolve IP address for hostname 
      struct hostent *host; 
      if((host=gethostbyname(szServer))==NULL) 
      { 
       MessageBox(hWnd, 
        "Unable to resolve host name", 
        "Critical Error", 
        MB_ICONERROR); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 

      // Set up our socket address structure 
      SOCKADDR_IN SockAddr; 
      SockAddr.sin_port=htons(nPort); 
      SockAddr.sin_family=AF_INET; 
      SockAddr.sin_addr.s_addr=*((unsigned long*)host->h_addr); 

      connect(Socket,(LPSOCKADDR)(&SockAddr),sizeof(SockAddr)); 
     } 
     break; 

     case WM_COMMAND: 
      switch(LOWORD(wParam)) 
      { 
       case IDC_MAIN_BUTTON: 
       { 
        char szBuffer[1024]; 

        int test=sizeof(szBuffer); 
        ZeroMemory(szBuffer,sizeof(szBuffer)); 

        SendMessage(hEditOut, 
         WM_GETTEXT, 
         sizeof(szBuffer), 
         reinterpret_cast<LPARAM>(szBuffer)); 
        send(Socket,szBuffer,strlen(szBuffer),0); 
        SendMessage(hEditOut,WM_SETTEXT,NULL,(LPARAM)""); 
       } 
       break; 
      } 
      break; 

     case WM_DESTROY: 
     { 
      PostQuitMessage(0); 
      shutdown(Socket,SD_BOTH); 
      closesocket(Socket); 
      WSACleanup(); 
      return 0; 
     } 
     break; 

     case WM_SOCKET: 
     { 
      if(WSAGETSELECTERROR(lParam)) 
      { 
       MessageBox(hWnd, 
        "Connection to server failed", 
        "Error", 
        MB_OK|MB_ICONERROR); 
       SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       break; 
      } 
      switch(WSAGETSELECTEVENT(lParam)) 
      { 
       case FD_READ: 
       { 
        char szIncoming[1024]; 
        ZeroMemory(szIncoming,sizeof(szIncoming)); 

        int inDataLength=recv(Socket, 
         (char*)szIncoming, 
         sizeof(szIncoming)/sizeof(szIncoming[0]), 
         0); 

        strncat(szHistory,szIncoming,inDataLength); 
        strcat(szHistory,"\r\n"); 

        SendMessage(hEditIn, 
         WM_SETTEXT, 
         sizeof(szIncoming)-1, 
         reinterpret_cast<LPARAM>(&szHistory)); 
       } 
       break; 

       case FD_CLOSE: 
       { 
        MessageBox(hWnd, 
         "Server closed connection", 
         "Connection closed!", 
         MB_ICONINFORMATION|MB_OK); 
        closesocket(Socket); 
        SendMessage(hWnd,WM_DESTROY,NULL,NULL); 
       } 
       break; 
      } 
     } 
    } 

    return DefWindowProc(hWnd,msg,wParam,lParam); 
} 
+0

如果沒有精神技能,這是無法回答的。請添加一些代碼,以便我們看到你在做什麼。 –

+0

當套接字關閉時,爲什麼您要在服務器中發送'WM_DESTROY'?這可能會導致服務器應用程序退出,意味着客戶端_cant_再次連接,因爲沒有服務器偵聽。或者如果服務器沒有退出,它可能會停止正常工作。 –

+0

抱歉,錯誤的代碼在關閉期間不會有任何WM_DESTROY。但結果是一樣的... FD_READ突然停止響應。 –

回答

3

你有多個問題。首先是你在FD_READFD_WRITE事件的無源監聽插座上做WSAAsyncSelect。被動套接字將不會收到這些事件。第二個是你沒有在實際連接的插座上做WSAAsyncSelect

還有其他問題,最嚴重的是你只保留一個插座變量。這意味着當你接受時,你鬆開了「主」套接字,並且你不能有多個連接(每個新連接都會覆蓋套接字變量)。您也不會實際關閉FD_CLOSE上的套接字(它不會自動完成),並且可能還有更多的我目前尚未發現。