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; }