[질문] 소켓프로그래밍인데....좀 봐주세여
글쓴이: 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
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; }저부분이 잘못된건 아닌지요???
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); HANDLE_MSG(hWndDlg, WM_SOCKEVENT, OnSockEvent); } return FALSE; }뭐 대충 저렇게라도 해야 메시지가 도착했을때 프로시져가 처리하지 않을까요?
------------------------------
좋은 하루 되세요.
WM_SOCKEVENT 메시지는 다이얼로그프로시저에 전달되는게 아니라..
WM_SOCKEVENT 메시지는 다이얼로그프로시저에 전달되는게 아니라...
메인윈도우로 전달되는 걸로 알로 있는데여...
아닌가여? 아닌가.....-_-;
댓글 달기