2012-11-22 2 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'를 보내고 있습니까? 이로 인해 서 v 응용 프로그램이 종료 되 G로, 서 v가 청취하지 않으므로 클라이언트 _cant_가 다시 연결된다는 의미입니다. 또는 서버가 종료되지 않으면 제대로 작동하지 않을 수 있습니다. –

+0

죄송합니다 잘못된 코드는 닫을 때 WM_DESTROY가 없습니다. 그러나 결과는 동일합니다 ... FD_READ가 갑자기 응답하지 않습니다. –

답변

3

을 여러 문제가있다. 첫 번째는 및 FD_WRITE 이벤트의 수동 수신 소켓에서 WSAAsyncSelect을 수행한다는 것입니다. 수동 소켓은 이러한 이벤트를 수신하지 않습니다. 두 번째는 실제 연결된 소켓 WSAAsyncSelect을 수행하지 않는다는 것입니다.

다른 문제도 있습니다. 가장 심각한 것은 소켓에 대해 하나의 변수 만 유지한다는 것입니다. 즉, 수락 할 때 "마스터"소켓이 느슨하게 연결되어 있고 여러 개의 연결 (새 연결마다 소켓 변수를 덮어 씀)을 사용할 수 없다는 의미입니다. 또한 소켓을 실제로 닫지 않고 FD_CLOSE (자동으로 수행되지는 않음)하고, 지금까지 발견하지 못한 것이 더 많습니다.

관련 문제