Created
December 17, 2013 20:01
-
-
Save jtrindade/8011607 to your computer and use it in GitHub Desktop.
Asynchronous echo server (incomplete)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#undef UNICODE | |
#define WIN32_LEAN_AND_MEAN | |
#include <windows.h> | |
#include <winsock2.h> | |
#include <ws2tcpip.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
// Need to link with Ws2_32.lib | |
#pragma comment (lib, "Ws2_32.lib") | |
// #pragma comment (lib, "Mswsock.lib") | |
#define DEFAULT_BUFLEN 512 | |
#define DEFAULT_PORT "27015" | |
#define NUM_WORKER_THREADS 4 | |
struct ClientSession { | |
WSAOVERLAPPED Overlapped; | |
SOCKET ClientSocket; | |
char RecvBuf[DEFAULT_BUFLEN]; | |
WSABUF WsaBuf; | |
}; | |
DWORD __stdcall WorkerThread(LPVOID _iocp) { | |
HANDLE iocp = (HANDLE)_iocp; | |
struct ClientSession * Session; | |
printf(":: WORKER STARTED ::\n"); | |
for (;;) { | |
DWORD numberOfBytes; | |
ULONG_PTR completionKey; | |
LPOVERLAPPED overlapped; | |
GetQueuedCompletionStatus( | |
iocp, | |
&numberOfBytes, | |
&completionKey, | |
&overlapped, | |
INFINITE | |
); | |
Session = (struct ClientSession *)overlapped; | |
if (numberOfBytes == 0) { | |
printf("-- Connection closed --\n"); | |
shutdown(Session->ClientSocket, SD_SEND); | |
closesocket(Session->ClientSocket); | |
free(Session); | |
break; | |
} else { | |
DWORD Flags = 0; | |
printf(".. received %d bytes\n", numberOfBytes); | |
WSARecv(Session->ClientSocket, &Session->WsaBuf, 1, NULL, &Flags, overlapped, NULL); | |
} | |
} | |
return 0; | |
} | |
int __cdecl main(void) | |
{ | |
WSADATA wsaData; | |
int iResult; | |
SOCKET ListenSocket = INVALID_SOCKET; | |
SOCKET ClientSocket = INVALID_SOCKET; | |
struct addrinfo *result = NULL; | |
struct addrinfo hints; | |
int iSendResult; | |
char recvbuf[DEFAULT_BUFLEN]; | |
int recvbuflen = DEFAULT_BUFLEN; | |
HANDLE iocp; | |
int i; | |
struct ClientSession * Session; | |
// Initialize Winsock | |
iResult = WSAStartup(MAKEWORD(2,2), &wsaData); | |
if (iResult != 0) { | |
printf("WSAStartup failed with error: %d\n", iResult); | |
return 1; | |
} | |
ZeroMemory(&hints, sizeof(hints)); | |
hints.ai_family = AF_INET; | |
hints.ai_socktype = SOCK_STREAM; | |
hints.ai_protocol = IPPROTO_TCP; | |
hints.ai_flags = AI_PASSIVE; | |
// Resolve the server address and port | |
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); | |
if ( iResult != 0 ) { | |
printf("getaddrinfo failed with error: %d\n", iResult); | |
WSACleanup(); | |
return 1; | |
} | |
// Create a SOCKET for connecting to server | |
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); | |
if (ListenSocket == INVALID_SOCKET) { | |
printf("socket failed with error: %ld\n", WSAGetLastError()); | |
freeaddrinfo(result); | |
WSACleanup(); | |
return 1; | |
} | |
// Setup the TCP listening socket | |
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen); | |
if (iResult == SOCKET_ERROR) { | |
printf("bind failed with error: %d\n", WSAGetLastError()); | |
freeaddrinfo(result); | |
closesocket(ListenSocket); | |
WSACleanup(); | |
return 1; | |
} | |
freeaddrinfo(result); | |
/* Cria o I/O completion port com factor de concorrência igual | |
ao número de processadores. */ | |
iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); | |
for (i = 0; i < NUM_WORKER_THREADS; ++i) { | |
CreateThread(NULL, 0, WorkerThread, iocp, 0, NULL); | |
} | |
iResult = listen(ListenSocket, SOMAXCONN); | |
if (iResult == SOCKET_ERROR) { | |
printf("listen failed with error: %d\n", WSAGetLastError()); | |
closesocket(ListenSocket); | |
WSACleanup(); | |
return 1; | |
} | |
for (;;) { | |
DWORD Flags = 0; | |
// Accept a client socket | |
ClientSocket = accept(ListenSocket, NULL, NULL); | |
if (ClientSocket == INVALID_SOCKET) { | |
printf("accept failed with error: %d\n", WSAGetLastError()); | |
closesocket(ListenSocket); | |
WSACleanup(); | |
return 1; | |
} | |
printf("++ Connection established ++ \n"); | |
Session = (struct ClientSession *)malloc(sizeof (struct ClientSession)); | |
Session->ClientSocket = ClientSocket; | |
Session->WsaBuf.buf = Session->RecvBuf; | |
Session->WsaBuf.len = sizeof Session->RecvBuf; | |
// Associar o socket ao I/O completion port | |
CreateIoCompletionPort((HANDLE)ClientSocket, iocp, (ULONG_PTR)NULL, 0); | |
// Iniciar leitura assíncrona | |
ZeroMemory(&Session->Overlapped, sizeof (WSAOVERLAPPED)); | |
WSARecv(ClientSocket, &Session->WsaBuf, 1, NULL, &Flags, (LPWSAOVERLAPPED)Session, NULL); | |
} | |
// No longer need server socket | |
closesocket(ListenSocket); | |
WSACleanup(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment