Windows Socket API. Win32 API 에 기본적으로 지원한다.
일반적인 버클리 소켓 스타일과 Windows 자체 스타일의 비동기소켓 (윈도우 메세지를 이용하는 방법, IOCP) API 를 제공해준다.
다음은 화일보내고 받기 관련 Winsock API 간단 예제. (옛날 예제삼아 만든 소스여서 직관적이지가 않긴 하군 -_-; 그냥 이해의 차원정도)
보내기 소스 (서버) ¶
서버의 경우 1 user 1 thread 임.
~cpp
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <process.h>
DWORD WINAPI Threading (LPVOID args)
{
SOCKET* pSocket = (SOCKET*)args;
SOCKET socket = *pSocket;
HANDLE hFileIn;
char szBuffer[8192]="";
DWORD nRead, nWrite, i;
DWORD dwLow, dwHigh;
int nSended;
hFileIn = CreateFile ("d:\test.mp3", GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, NULL, NULL);
// send (*pSocket, "Data", 5, NULL);
dwLow = GetFileSize (hFileIn, &dwHigh);
for (i=0;i<dwLow;) {
SetFilePointer (hFileIn, i, NULL, FILE_BEGIN);
ReadFile (hFileIn, szBuffer, sizeof (szBuffer), &nRead, NULL);
nSended = send (socket, szBuffer, nRead, NULL);
i+= max (0, nSended);
if (nSended == SOCKET_ERROR) {
printf ("Error : %d n", WSAGetLastError ());
}
else {
printf ("Current : %d / %d (%d)n", dwLow, i, nSended);
}
Sleep (100);
}
CloseHandle (hFileIn);
return 0;
}
int main (void)
{
WSADATA wsaData;
sockaddr_in local, from;
SOCKET socketListen;
SOCKET socketClient;
WSACleanup ();
DWORD dwTemp;
if (WSAStartup (0x202, &wsaData) == SOCKET_ERROR) {
printf ("error.. %dn", WSAGetLastError ());
WSACleanup ();
return 0;
}
local.sin_family = AF_INET;
local.sin_addr.s_addr = INADDR_ANY;
local.sin_port = htons (5000);
socketListen = socket (AF_INET, SOCK_STREAM, IPPROTO_IP);
if (socketListen == INVALID_SOCKET) {
printf ("create socket error.. %dn", WSAGetLastError ());
WSACleanup ();
return 0;
}
if (bind (socketListen, (sockaddr *)&local, sizeof (local)) == SOCKET_ERROR) {
printf ("bind error.. %dn", WSAGetLastError ());
WSACleanup ();
return 0;
}
if (listen (socketListen, 5) == SOCKET_ERROR) {
printf ("listen error.. %dn", WSAGetLastError ());
WSACleanup ();
return 0;
}
BOOL bFlag = TRUE;
WSAEVENT hEvent = WSACreateEvent ();
WSAEVENT hEvent2 = WSACreateEvent ();
WSAEVENT Eventarry[2];
Eventarry[0] = hEvent;
Eventarry[1] = hEvent2;
WSANETWORKEVENTS NetworkEvents;
DWORD WaitStatus;
int addlen = sizeof (from);
WSAEventSelect (socketListen, hEvent, FD_ALL_EVENTS);
printf ("Waiting.. n");
while (bFlag) {
WaitStatus = WSAWaitForMultipleEvents (2, Eventarry, FALSE, 1000, FALSE);
if (WaitStatus == WSA_WAIT_EVENT_0) {
if (WSAEnumNetworkEvents (socketListen, hEvent, &NetworkEvents) != 0) {
printf ("Error.... %dn", GetLastError ());
bFlag = 0;
}
if (NetworkEvents.lNetworkEvents & FD_ACCEPT) {
if (NetworkEvents.iErrorCode [FD_ACCEPT_BIT] == 0) {
socketClient = accept (socketListen, (sockaddr *)&from, &addlen);
printf ("Accepted... !n");
//send (socketClient, "hugugu~rn", 9, NULL);
CreateThread (NULL, NULL, Threading, &socketClient, NULL, &dwTemp);
WSAEventSelect (socketClient, hEvent2, FD_ALL_EVENTS);
}
}
}
if (WaitStatus == (WSA_WAIT_EVENT_0 + 1) ) {
if (WSAEnumNetworkEvents (socketClient, hEvent2, &NetworkEvents) != 0) {
printf ("Error.... %dn", GetLastError ());
// bFlag = 0;
}
/*
if (NetworkEvents.lNetworkEvents & FD_READ) {
DWORD dwDataReaded;
char* szBuffer;
printf ("Data Received... n");
ioctlsocket (socketClient, FIONREAD, &dwDataReaded);
szBuffer = (char *)LocalAlloc (LPTR, dwDataReaded);
recv (socketClient, szBuffer, dwDataReaded, NULL);
printf ("Data : %s (%d)n", szBuffer, dwDataReaded);
LocalFree (szBuffer);
}
*/
if (NetworkEvents.lNetworkEvents & FD_CLOSE) {
closesocket (socketClient);
printf ("closed... !n");
// bFlag = 0;
}
}
}
printf ("Program end.. n");
WSACloseEvent (hEvent);
WSACloseEvent (hEvent2);
WSACleanup ();
return 0;
}
받기 소스 (클라이언트) ¶
~cpp
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
int main (void)
{
WSADATA wsaData;
sockaddr_in local, from;
SOCKET socketClient;
SOCKADDR_IN ServerAddress; //소켓의 주소
int i=0;
int nSize;
WSACleanup ();
DWORD dwTemp;
HANDLE hFileOut;
DWORD nWrite;
if (WSAStartup (0x202, &wsaData) == SOCKET_ERROR) {
printf ("error.. %dn", WSAGetLastError ());
WSACleanup ();
return 0;
}
char szCommand[8]="";
char szHostName[40];
gethostname(szHostName, sizeof(szHostName));
HOSTENT FAR* lphostent = ::gethostbyname(szHostName);
printf ("IP : %s n",inet_ntoa(*((struct in_addr*)lphostent->h_addr)));
socketClient = socket (AF_INET, SOCK_STREAM, IPPROTO_IP);
if (socketClient == INVALID_SOCKET) {
printf ("create socket error.. %dn", WSAGetLastError ());
WSACleanup ();
return 0;
}
ServerAddress.sin_family = AF_INET;
//IP주소값. INADDR_ANY는 아무거나입니다. ^^;
ServerAddress.sin_addr.s_addr = inet_addr( "127.0.0.1" );
ServerAddress.sin_port = htons( 1002 ); //포트번호
connect (socketClient, (struct sockaddr*)&ServerAddress, sizeof (ServerAddress));
WSAEVENT hEvent = WSACreateEvent ();
WSANETWORKEVENTS NetworkEvents;
DWORD WaitStatus;
WSAEventSelect (socketClient, hEvent, FD_ALL_EVENTS);
hFileOut = CreateFile ("testdata.mp3", GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
while (1) {
WaitStatus = WSAWaitForMultipleEvents (1, &hEvent, FALSE, 10, FALSE);
if (WaitStatus == WSA_WAIT_EVENT_0) {
if (WSAEnumNetworkEvents (socketClient, hEvent, &NetworkEvents) != 0) {
printf ("Error.... %dn", GetLastError ());
}
if (NetworkEvents.lNetworkEvents & FD_CONNECT) {
if (NetworkEvents.iErrorCode [FD_CONNECT_BIT] == 0) {
printf ("Connect... !n");
// TEST_FILE_REQUARE 0xF0
szCommand[0] = 0xF0;
send (socketClient, szCommand, 8, NULL);
}
}
if (NetworkEvents.lNetworkEvents & FD_READ) {
DWORD dwDataReaded;
char* szBuffer;
ioctlsocket (socketClient, FIONREAD, &dwDataReaded);
szBuffer = (char *)LocalAlloc (LPTR, dwDataReaded);
recv (socketClient, szBuffer, dwDataReaded, NULL);
WriteFile (hFileOut, szBuffer, dwDataReaded, &nWrite, NULL);
i+= dwDataReaded;
printf ("Data Received... %d (%d)n", i, dwDataReaded);
LocalFree (szBuffer);
}
}
}
closesocket (socketClient);
WSACleanup ();
return 0;
}









