基于异步选择模型的服务器实践

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Datura_Metel/article/details/79973675
#include "winsock2.h"
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
using namespace std;
#define MAXDATASIZE 200

typedef struct _SOCKET_INFORMATION
{
    char buf[MAXDATASIZE];
    WSABUF DataBuf;
    SOCKET Socket;
    _SOCKET_INFORMATION *Next;

}SOCKET_INFORMATION, *LPSOCKET_INFORMATION;

#define BACKLOG 5
#define WM_SOCKET (WM_USER + 1)
LPSOCKET_INFORMATION SocketInfoList = NULL;
char buf[MAXDATASIZE];
SOCKET Accept;

void CreateSocketInformation(SOCKET s)
{
    LPSOCKET_INFORMATION SI;
    SI = (LPSOCKET_INFORMATION)GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION));
    if (SI == NULL)
    {
        printf("GlobalAlloc() failed with error %d.\n", GetLastError());
        return;
    }
    SI->Socket = s;
    SI->Next = SocketInfoList;
    SocketInfoList = SI;
}

LPSOCKET_INFORMATION GetSocketInformation(SOCKET s)
{
    LPSOCKET_INFORMATION SI = SocketInfoList;
    while (SI)
    {
        if (SI->Socket == s)
            return SI;
        SI = SI->Next;
    }
    return NULL;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    LPSOCKET_INFORMATION SocketInfo;
    int sb, BytesRecv = 0;
    if (uMsg == WM_SOCKET)
    {
        if (WSAGETSELECTERROR(lParam))
        {
            printf("Socket failed with error %d.\n", WSAGETSELECTERROR(lParam));
        }
        else
        {
            switch (WSAGETSELECTEVENT(lParam))
            {
            case FD_ACCEPT:
                Accept = accept(wParam, NULL, NULL);
                if (Accept == INVALID_SOCKET)
                {
                    printf("accept() failed with error %d.\n", WSAGetLastError());
                    break;
                }
                WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ | FD_WRITE | FD_CLOSE);
                CreateSocketInformation(Accept);
                break;
            case FD_READ:
                SocketInfo = GetSocketInformation(wParam);
                BytesRecv = recv(SocketInfo->Socket, buf, MAXDATASIZE, 0);
                if (BytesRecv > 0)
                {
                    buf[BytesRecv] = '\0';
                    printf("recv : %s\n", buf);
                }
                break;
            case FD_CLOSE:
                SocketInfo = GetSocketInformation(wParam);
                printf("Socket %d closed.\n", SocketInfo->Socket);
                closesocket(SocketInfo->Socket);
                break;
            }
        }
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

HWND MakeWorkerWindow(void)
{
    WNDCLASSEX wndclass;
    WCHAR ProviderClass[] = L"AsyncSelect";
    WCHAR WindowName[] = L"";
    HWND Window;

    wndclass.cbSize = sizeof(wndclass);
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = (WNDPROC)WindowProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = NULL;
    wndclass.hIcon = LoadIcon(NULL, IDI_WARNING);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = ProviderClass;
    wndclass.hIconSm = NULL;
    if (RegisterClassEx(&wndclass) == 0)
    {
        printf("RegisterClassEx() failed with error %d.\n", GetLastError());
        return NULL;
    }
    Window = CreateWindow(ProviderClass, WindowName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, NULL, NULL, NULL, NULL);
    if (Window == NULL)
    {
        printf("CreateWindow() failed with error %d.\n", GetLastError());
        return NULL;
    }
    return Window;
}

int main()
{
    MSG msg;
    DWORD ret;
    
    HWND Window = MakeWorkerWindow();
    if (Window == NULL)
    {
        return 0;
    }
    WSADATA wsadata;
    WSAStartup(0x0202, &wsadata);

    SOCKET sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    WSAAsyncSelect(sockfd, Window, WM_SOCKET, FD_ACCEPT);

    struct sockaddr_in myaddr;
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(27105);
    myaddr.sin_addr.s_addr = INADDR_ANY;
    bind(sockfd, (SOCKADDR*)&myaddr, sizeof(myaddr));
    listen(sockfd, BACKLOG);

    printf("Server starts listening...\n");
    while (ret = GetMessage(&msg, NULL, 0, 0))
    {
        if (ret == -1)
        {
            printf("GetMessage failed with error %d.\n", GetLastError());
            return 0;
        }
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    closesocket(sockfd);
    WSACleanup();
    system("pause");
    return 0;
}
阅读更多

没有更多推荐了,返回首页