Skip to content

Instantly share code, notes, and snippets.

@jtrindade
Created December 17, 2013 20:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jtrindade/8011607 to your computer and use it in GitHub Desktop.
Save jtrindade/8011607 to your computer and use it in GitHub Desktop.
Asynchronous echo server (incomplete)
#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