📄 asyncserver.cpp
字号:
return;
printf("\n");
bps = gBytesSent / elapsed;
printf("Average BPS sent: %lu [%lu]\n", bps, gBytesSent);
bps = gBytesRead / elapsed;
printf("Average BPS read: %lu [%lu]\n", bps, gBytesRead);
elapsed = (tick - gStartTimeLast) / 1000;
if (elapsed == 0)
return;
bps = gBytesSentLast / elapsed;
printf("Current BPS sent: %lu\n", bps);
bps = gBytesReadLast / elapsed;
printf("Current BPS read: %lu\n", bps);
printf("Current Connections: %lu\n", gCurrentConnections);
InterlockedExchange(&gBytesSentLast, 0);
InterlockedExchange(&gBytesReadLast, 0);
gStartTimeLast = tick;
}
//
// Function: WindowProc
//
// Description:
// This is the window procedure which handles the window messages for
// our hidden window. It handles all the WM_SOCKET messages and performs
// the correct actions for each message type (FD_READ, FD_WRITE, etc.).
//
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SOCKET_OBJ *sockobj=NULL,
*newsock=NULL;
int rc;
if (uMsg == WM_SOCKET)
{
// Check for an error on the socket
if (WSAGETSELECTERROR(lParam))
{
// An error occured on the socket, close it down
fprintf(stderr, "Socket failed with error %d\n", WSAGETSELECTERROR(lParam));
closesocket(wParam);
RemoveSocketObjByHandle(wParam);
}
else
{
// Find the socket object for this event
sockobj = FindSocketObj(wParam);
if (sockobj == NULL)
return 0;
switch (WSAGETSELECTEVENT(lParam))
{
case FD_ACCEPT:
// Get a new object for the client socket
newsock = GetSocketObj(INVALID_SOCKET);
newsock->s = accept(
wParam,
(SOCKADDR *)&newsock->addr,
&newsock->addrlen
);
if (newsock->s == INVALID_SOCKET)
{
fprintf(stderr, "accept failed: %d\n", WSAGetLastError());
break;
}
InterlockedIncrement(&gCurrentConnections);
// Create a socket information structure to associate with the
// socket for processing I/O.
InsertSocketObj(newsock);
/*
printf("Accepted connection from: ");
PrintAddress((SOCKADDR *)&newsock->addr, newsock->addrlen);
printf("\n");
*/
rc = WSAAsyncSelect(
newsock->s,
hwnd,
WM_SOCKET,
FD_READ | FD_WRITE | FD_CLOSE
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "WSAAsyncSelect failed: %d\n", WSAGetLastError());
return -1;
}
break;
case FD_READ:
rc = ReceivePendingData(sockobj);
if (rc == -1)
{
RemoveSocketObj(sockobj);
break;
}
else if (rc != WSAEWOULDBLOCK)
{
PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
}
//
// Don't break fall through and attempt to send data
//
case FD_WRITE:
//
// Send routine automatically tries to send all queued buffers.
//
rc = SendPendingData(sockobj);
if (rc == -1)
{
RemoveSocketObj(sockobj);
}
break;
case FD_CLOSE:
sockobj->closing = TRUE;
//
// Post an FD_READ message to force another receive
// This is to ensure we recv() until 0 is returned.
//
PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
break;
default:
printf("Unknown message received: %d\n", WSAGETSELECTEVENT(lParam));
break;
}
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
//
// Function: MakeWorkerWindow
//
// Description:
// Create a hidden window to receive our socket messages.
//
HWND MakeWorkerWindow(void)
{
WNDCLASS wndclass;
CHAR *ProviderClass = "AsyncSelect";
HWND Window;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = (WNDPROC)WindowProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = NULL;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = ProviderClass;
if (RegisterClass(&wndclass) == 0)
{
fprintf(stderr, "RegisterClass() failed with error %d\n", GetLastError());
return NULL;
}
// Create a window.
if ((Window = CreateWindow(
ProviderClass,
"",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
NULL,
NULL)) == NULL)
{
fprintf(stderr, "CreateWindow() failed with error %d\n", GetLastError());
return NULL;
}
return Window;
}
//
// Function: StatisticsThread
//
// Description:
// Simple thread to print the statistics out. In this model there isn't
// a good place to incorporate it into the normal program flow.
//
DWORD WINAPI StatisticsThread(LPVOID lpParam)
{
while (1)
{
SleepEx(5000, TRUE);
PrintStatistics();
}
ExitThread(0);
return 0;
}
//
// Function: main
//
// Description:
// This is the main program. It parses the command line and creates
// the main socket. For UDP this socket is used to receive datagrams.
// For TCP the socket is used to accept incoming client connections.
// Each client TCP connection is handed off to a worker thread which
// will receive any data on that connection until the connection is
// closed.
//
int __cdecl main(int argc, char **argv)
{
WSADATA wsd;
SOCKET_OBJ *sockobj=NULL,
*sptr=NULL,
*tmp=NULL;
HANDLE hThread;
ULONG lastprint=0;
MSG msg;
int rc;
struct addrinfo *res=NULL,
*ptr=NULL;
ValidateArgs(argc, argv);
InitializeCriticalSection(&gSocketCritSec);
// Load winsock
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
fprintf(stderr, "unable to load Winsock!\n");
return -1;
}
gWorkerWindow = MakeWorkerWindow();
printf("Local address: %s; Port: %s; Family: %d\n",
gBindAddr, gBindPort, gAddressFamily);
res = ResolveAddress(gBindAddr, gBindPort, gAddressFamily, gSocketType, gProtocol);
if (res == NULL)
{
fprintf(stderr, "ResolveAddress failed to return any addresses!\n");
return -1;
}
// For each local address returned, create a listening/receiving socket
ptr = res;
while (ptr)
{
PrintAddress(ptr->ai_addr, ptr->ai_addrlen); printf("\n");
sockobj = GetSocketObj(INVALID_SOCKET);
// create the socket
sockobj->s = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
if (sockobj->s == INVALID_SOCKET)
{
fprintf(stderr,"socket failed: %d\n", WSAGetLastError());
return -1;
}
InsertSocketObj(sockobj);
// bind the socket to a local address and port
rc = bind(sockobj->s, ptr->ai_addr, ptr->ai_addrlen);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
return -1;
}
if (gProtocol == IPPROTO_TCP)
{
rc = listen(sockobj->s, 200);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "listen failed: %d\n", WSAGetLastError());
return -1;
}
// Register for notification
rc = WSAAsyncSelect(
sockobj->s,
gWorkerWindow,
WM_SOCKET,
FD_ACCEPT | FD_CLOSE
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "WSAAsyncSelect failed: %d\n", WSAGetLastError());
return -1;
}
}
else
{
// Register for notification
rc = WSAAsyncSelect(
sockobj->s,
gWorkerWindow,
WM_SOCKET,
FD_READ | FD_WRITE | FD_CLOSE
);
if (rc == SOCKET_ERROR)
{
fprintf(stderr, "WSAAsyncSelect failed: %d\n", WSAGetLastError());
return -1;
}
}
ptr = ptr->ai_next;
}
// free the addrinfo structure for the 'bind' address
freeaddrinfo(res);
gStartTime = gStartTimeLast = lastprint = GetTickCount();
// Start a thread to print statistics
hThread = CreateThread(NULL, 0, StatisticsThread, NULL, 0, NULL);
if (hThread == NULL)
{
fprintf(stderr, "CreateThread failed: %d\n", WSAGetLastError());
return -1;
}
CloseHandle(hThread);
while(rc = GetMessage(&msg, NULL, 0, 0))
{
if (rc == -1)
{
fprintf(stderr, "GetMessage() failed with error %d\n", GetLastError());
return -1;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
WSACleanup();
DeleteCriticalSection(&gSocketCritSec);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -