[질문] 소켓프로그래밍인데....좀 봐주세여
글쓴이: pcguy7 / 작성시간: 목, 2003/11/06 - 4:54오후
비동기 소켓이 작동이 안하는것 같아요..
서버에서 패킷을 보내두 소켓이벤트가 발생하지 않는것 같아요...
뭐가 잘못된건지..아시는 분은 답변좀 해주세여..제발요...
참고로 헤더파일은 생략할께여..
#include "KOREA client.h" int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow ) { MSG msg; // 소켓 초기화 WSADATA wsaData; WSAStartup( MAKEWORD( 2, 2 ), &wsaData ); // 윈도우 클래스 초기화 WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = NULL; wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground = CreateSolidBrush( RGB( 255, 255, 255 ) ); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; // 클래스 등록 RegisterClass( &wndclass ); // 메인 윈도우 생성 HWND hwnd = CreateWindow( szAppName, szAppName, WS_SYSMENU | WS_VISIBLE | WS_MINIMIZEBOX, 200, // 윈도우 좌상단 좌표 200, 360, // 윈도우 크기 440, NULL, NULL, // 메뉴 핸들 hInstance, NULL ); // 윈도우 화면 표시 ShowWindow( hwnd, nCmdShow ); UpdateWindow( hwnd ); g_hWnd = hwnd; g_hInst = hInstance; // 메시지 루프 while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage( &msg ); DispatchMessage( &msg ); } // 소켓 종료화 WSACleanup(); return (int) msg.wParam ; } /*************************************************************************************************************/ /* */ /* 1. 윈도우 프로시저 */ /* 2. 윈도우에서 발행한 메시지를 처리한다. */ /* */ /*************************************************************************************************************/ LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ) { HANDLE_MSG(hWnd, WM_CREATE, OnCreate); HANDLE_MSG(hWnd, WM_SOCKEVENT, OnSockEvent); HANDLE_MSG(hWnd, WM_LBUTTONDOWN, OnLButtonDown); HANDLE_MSG(hWnd, WM_PAINT, OnPaint); HANDLE_MSG(hWnd, WM_DESTROY, OnDestroy); } return DefWindowProc( hWnd, message, wParam, lParam ); } // 디버거용 void OnLButtonDown(HWND hwnd, BOOL fDoubleClick, int x, int y, UINT keyFlags) { } // WM_CREATE 메시지 핸들러 BOOL OnCreate( HWND hWnd, LPCREATESTRUCT lpCreateStruct ) { // 메인 윈도우 표시하기 전에 IP 적는 다이얼로그 박스 표시 DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_LOGIN), hWnd, DialogProc, IDD_LOGIN); return TRUE; } // WM_PAINT 메시지 핸들러 void OnPaint(HWND hWnd) { HDC hdc; PAINTSTRUCT ps; static int y = 1; hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps); } // WM_DESTROY 메시지 핸들러 // 1. 프로그램을 종료시킵니다. void OnDestroy( HWND hWnd ) { PostQuitMessage( 0 ); } /*************************************************************************************************************/ /* */ /* 1. 다이얼로그 프로시저 */ /* 2. 다이얼로그에서 발행한 메시지를 처리한다. */ /* */ /*************************************************************************************************************/ BOOL CALLBACK DialogProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { HANDLE_MSG(hWndDlg, WM_INITDIALOG, OnInitDialog); HANDLE_MSG(hWndDlg, WM_COMMAND, OnDlgCommand); } return FALSE; } // WM_INITDIALOG 메시지 핸들러 BOOL OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam) { // IP 콘트롤에 포커스 옮김 SetFocus(GetDlgItem(hWnd, IDC_IP)); return TRUE; } // WM_COMMAND 메시지 핸들러 void OnDlgCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify) { // 다일얼로그 박스에 확인 버튼을 누르면 if (id == IDOK) { DWORD dwIP; char ID[STRSIZE]; sockaddr_in ServerAddr; // IP 주소 저장한다 SendMessage(GetDlgItem(hWnd, IDC_IP), IPM_GETADDRESS, 0, (LPARAM)&dwIP); // ID 를 읽어온다 GetDlgItemText(hWnd, IDC_ID, ID, sizeof(ID)); // 소켓 생성 if ((g_hClientSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { MessageBox(hWnd, "socket() 함수 에러", NULL, MB_OK); return; } // 주소 구조체 0 으로 초기화 ZeroMemory(&ServerAddr, sizeof(ServerAddr)); // 서버 주소 구조체 설정 ServerAddr.sin_family = AF_INET; ServerAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); ServerAddr.sin_port = htons(PORT); // 연결요청을 하고 실패하면 에러 표시 if (connect(g_hClientSocket, (sockaddr *)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR) { MessageBox(hWnd, "connect() 함수 에러", NULL, MB_OK); return; } // 연결 요청이 되면 else { // 접속함과 동시에 ID 를 전송 // 서버는 받은 ID 를 g_hClientDataList 리스트에 저장한다 SendPacket(g_hClientSocket, PACKET_LOGIN, ID, lstrlen(ID)); // 여기에서 소켓을 비동기로 설정했는데 작동이 안되는것 같아요...왜 그런거죠?? // 클라이언트 소켓을 비동기 소켓으로 전환 if (WSAAsyncSelect(g_hClientSocket, hWnd, WM_SOCKEVENT, FD_READ | FD_CLOSE) == SOCKET_ERROR) { MessageBox(hWnd, "WSAAsyncSelect() 함수 에러", NULL, MB_OK); return; } EndDialog(hWnd, 0); } } // 취소 버튼을 누르면 else if (id == IDCANCEL) { EndDialog(hWnd, 0); PostQuitMessage(0); } } /*************************************************************************************************************/ /* */ /* 1. 소켓 이벤트 메시지 핸들러에서 발생한 이벤트에 대한 함수 처리 */ /* */ /*************************************************************************************************************/ void OnSockEvent( HWND hWnd, SOCKET socket, int nEvent, int nErrorCode ) { MessageBox(hWnd, "OnSockEvent 함수 호출", NULL, MB_OK); switch (nEvent) { case FD_READ : OnRead(hWnd, socket); break; case FD_CLOSE : OnClose(hWnd, socket); break; } } // FD_READ 소켓 이벤트 메시지 핸들러 // 데이터가 들어오는걸 수신한다 void OnRead(HWND hWnd, SOCKET socket) { PACKETFLAG PacketFlag; char *pData = NULL; int nDataSize; // 데이터 수신 if (ReadPacket(hWnd, socket, &nDataSize, &PacketFlag, &pData) == FALSE) { MessageBox(hWnd, "ReadPacket() 함수 에러", NULL, MB_OK); return; } // 데이터 가공 수신 ProcessClientPacket(socket, PacketFlag, pData, nDataSize); delete [] pData; } void OnClose(HWND hWnd, SOCKET socket) { MessageBox(hWnd, "서버 프로그램이 종료되었습니다", NULL, MB_OK); closesocket(socket); PostQuitMessage(0); } /*************************************************************************************************************/ /* */ /* 1. 그 밖의 함수들 */ /* */ /*************************************************************************************************************/ // 1. 패킷을 읽어옵니다. 읽어올 때, 헤더와 데이터를 분리합니다. // 2. 헤더나 데이터 전체를 읽기 전까지 프로그램은 블로킹 상태에 빠집니다. // 3. 예기치 않은 소켓 에러가 발생하면, 프로그램을 종료합니다. // 4. ppData 인자에 동적으로 할당한 메모리를 반환합니다. // 따라서, 이 함수를 호출한 곳에서 반드시 메모리를 책임지고 해제해야 합니다. BOOL ReadPacket( HWND hwnd, SOCKET socket, int* pDataSize, PACKETFLAG* pPacketFlag, char** ppData ) { // 패킷 헤더 읽기 : 패킷 길이 + 패킷 식별자 int pHeader[2]; int nRecvSize = 0, nTotalRecvSize = 0; while( nTotalRecvSize < sizeof( pHeader ) ) { nRecvSize = recv( socket, (char*) pHeader + nTotalRecvSize, sizeof( pHeader ) - nTotalRecvSize, 0 ); if( nRecvSize != SOCKET_ERROR ) { nTotalRecvSize += nRecvSize; continue; } if( WSAGetLastError() != WSAEWOULDBLOCK ) { assert( FALSE ); FORWARD_WM_DESTROY( hwnd, SendMessage ); } return FALSE; } assert( nTotalRecvSize == sizeof( pHeader ) ); // 패킷 데이터 읽기 : 패킷 길이 - 헤더 길이 int nDataSize = pHeader[0] - nTotalRecvSize; char* pPacketData = new char[nDataSize+1]; pPacketData[nDataSize] = '\0'; nTotalRecvSize = 0; while( nTotalRecvSize < nDataSize ) { nRecvSize = recv( socket, pPacketData + nTotalRecvSize, nDataSize - nTotalRecvSize, 0 ); if( nRecvSize != SOCKET_ERROR ) { nTotalRecvSize += nRecvSize; continue; } if( WSAGetLastError() != WSAEWOULDBLOCK ) { assert( FALSE ); FORWARD_WM_DESTROY( hwnd, SendMessage ); return FALSE; } } assert( nTotalRecvSize == nDataSize ); // 데이터 반환 *pDataSize = nDataSize; *pPacketFlag = (PACKETFLAG) pHeader[1]; *ppData = pPacketData; return TRUE; } // 1. 서버 프로그램으로 전달된 패킷을 처리합니다. // 2. 처리된 패킷을 가공해서 한다. void ProcessClientPacket( SOCKET socket, PACKETFLAG PacketFlag, char* pData, int nDataSize ) { switch( PacketFlag ) { case PACKET_CURRENTUSER : MessageBox(g_hWnd, pData, "서버에 현재 접속자", MB_OK); break; case PACKET_CLOSE : MessageBox(g_hWnd, pData, "접속자 연결 종료알림", MB_OK); break; default : assert( FALSE ); } } // 1. 패킷 전송 함수. // 2. 모든 종류의 패킷을 내부적으로 구성한 후 전송. // 3. 문자열 데이터의 경우, 길이에 NULL 문자는 포함하지 않습니다. int SendPacket( SOCKET socket, PACKETFLAG PacketFlag, void* pData, int nDataSize ) { static char pPacket[1024]; // 패킷 전체 길이 계산 int nPacketSize = sizeof( int ) + sizeof( PacketFlag ) + nDataSize; // 에러 처리 if( nPacketSize >= sizeof( pPacket ) ) return 0; // 패킷 구성 : 순서대로 패킷 길이, 패킷 식별자, 데이터 복사 MoveMemory( pPacket, &nPacketSize, sizeof( int ) ); MoveMemory( pPacket + sizeof( int ), & PacketFlag, sizeof( PacketFlag ) ); MoveMemory( pPacket + sizeof( int ) + sizeof( PacketFlag ), pData, nDataSize ); pPacket[nPacketSize] = '\0'; // 전송 return send( socket, pPacket, nPacketSize, 0 ); }
왜 비동기 소켓이 작동을 안하는 것일까요...
패키을 서버에서 분명히 보냈는데..send() 로
왜 받지를 못할까요...제발 답변좀 부탁드립니다..
완전한 파일 압축해서 첨부했습니다..
File attachments:
첨부 | 파일 크기 |
---|---|
![]() | 930.54 KB |
Forums:
[code:1]BOOL CALLBACK DialogProc(HWN
저부분이 잘못된건 아닌지요???
뭐 대충 저렇게라도 해야 메시지가 도착했을때 프로시져가 처리하지 않을까요?
------------------------------
좋은 하루 되세요.
WM_SOCKEVENT 메시지는 다이얼로그프로시저에 전달되는게 아니라..
WM_SOCKEVENT 메시지는 다이얼로그프로시저에 전달되는게 아니라...
메인윈도우로 전달되는 걸로 알로 있는데여...
아닌가여? 아닌가.....-_-;
댓글 달기