UDPサーバは、ソケットを生成してbindで待ち受けるだけです。 送信元の情報は、recvfromで受信する事で取得する事ができます。
#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#include <string>
#include <winsock2.h>
#include <windows.h>
#include <wingdi.h>
// ライブラリ
#pragma comment( lib, "ws2_32.lib" )
// WinSockからのイベント
#define WM_WINSOCKEVENT ( WM_USER + 100 )
// グローバル
SOCKET oSocket;
/*
メインウインドウイベント処理
*/
LRESULT CALLBACK eMainWindowProc
(
HWND hWnd // handle to window
, UINT uMsg // message identifier
, WPARAM wParam // first message parameter
, LPARAM lParam // second message parameter
)
{
switch( uMsg ) {
case WM_CREATE:
//--------------------------------------------
// WM_CREATE
//--------------------------------------------
{
CREATESTRUCT* tpCreateSt = (CREATESTRUCT*)lParam;
}
break;
case WM_WINSOCKEVENT:
//--------------------------------------------
// WM_WINSOCKEVENT
//--------------------------------------------
{
switch( WSAGETSELECTEVENT( lParam ) ) {
case FD_READ:
{
struct sockaddr_in oFromAddr;
int sockaddr_in_size = sizeof( struct sockaddr_in );
CHAR szData[ 256 ];
// 受信
::recvfrom(
oSocket
, (char*)szData
, sizeof( szData ) - 1
, 0
, (struct sockaddr*)&oFromAddr
, &sockaddr_in_size
);
// 受信元IPと内容を表示
printf( "%s, %s¥n", inet_ntoa( oFromAddr.sin_addr ), szData );
}
break;
}
}
break;
case WM_DESTROY:
//--------------------------------------------
// WM_DESTROY
//--------------------------------------------
{
// 終了する( 引数はそのまま終了コードとなります )
::PostQuitMessage( 0 );
}
break;
}
// デフォルト処理呼び出し
return ::DefWindowProc( hWnd, uMsg, wParam, lParam );
}
/*
UDPサーバ
*/
int _tmain
(
int argc
, _TCHAR* argv[]
)
{
// 標準出力にユニコードを表示できるようにする
setlocale( LC_ALL, "Japanese" );
// WinSockのスタートアップ
WSAData tWsaData;
WSAStartup( MAKEWORD(2,0), &tWsaData );
WNDCLASSEX tWndClass;
HINSTANCE hInstance;
TCHAR* cpClassName;
TCHAR* cpWindowName;
HWND hWnd;
// アプリケーションインスタンス
hInstance = ::GetModuleHandle( NULL );
// クラス名称
cpClassName = _T("MainWindowClass");
// ウインドウ名称
cpWindowName = _T("UDPサーバ");
// ウインドウクラスパラメータセット
tWndClass.cbSize = sizeof( WNDCLASSEX );
tWndClass.style = 0;
tWndClass.lpfnWndProc = eMainWindowProc;
tWndClass.cbClsExtra = 0; // ::GetClassLong で取得可能なメモリ
tWndClass.cbWndExtra = 0; // ::GetWindowLong で取得可能なメモリ
tWndClass.hInstance = hInstance;
tWndClass.hIcon = NULL;
tWndClass.hCursor = NULL;
tWndClass.hbrBackground = NULL;
tWndClass.lpszMenuName = NULL;
tWndClass.lpszClassName = cpClassName;
tWndClass.hIconSm = NULL;
// ウインドウクラス生成
if ( 0 == ::RegisterClassEx( &tWndClass ) ) {
/* 失敗 */
return( -1 );
}
// ウインドウを生成する(メッセージ専用)
hWnd = ::CreateWindowEx (
0 // extended window style
, tWndClass.lpszClassName // pointer to registered class name
, cpWindowName // pointer to window name
, WS_OVERLAPPEDWINDOW // window style
, CW_USEDEFAULT // horizontal position of window
, CW_USEDEFAULT // vertical position of window
, 640 // window width
, 480 // window height
, HWND_MESSAGE // handle to parent or owner window
, NULL // handle to menu, or child-window identifier
, hInstance // handle to application instance
, (VOID*)0x12345678 // pointer to window-creation data
);
// ソケットの生成
oSocket = socket( AF_INET, SOCK_DGRAM, 0 );
// ソケットを非同期にする
WSAAsyncSelect( oSocket, hWnd, WM_WINSOCKEVENT, FD_READ | FD_CLOSE );
struct sockaddr_in oSockAddr;
oSockAddr.sin_family = AF_INET;
oSockAddr.sin_port = htons( 12345 );
oSockAddr.sin_addr.S_un.S_addr = INADDR_ANY;
// バインド
::bind( oSocket, (struct sockaddr*)&oSockAddr, sizeof( oSockAddr ) );
// メッセージループ
::MessageBox( NULL, L"受信待ち", L"受信待ち", MB_OK );
// ソケットのクローズ
::closesocket( oSocket );
// WinSockのクリーンナップ
::WSACleanup();
// 正常終了
return( 0 );
}
