基于select模型的异步模式的服务器实践

在vs2015下调试

#include "winsock2.h"

#pragma comment(lib, "ws2_32.lib")
#include <iostream>
using namespace std;
#define DATA_BUFSIZE 200

typedef struct _SOCKET_INFORMATION
{
    char Buffer[DATA_BUFSIZE];
    WSABUF DataBuf;
    SOCKET Socket;
    DWORD BytesSend;
    DWORD BytesRecv;
}SOCKET_INFORMATION, * LPSOCKET_INFORMATION;

int TotalSocket = 0;
LPSOCKET_INFORMATION SocketArray[FD_SETSIZE];

BOOL 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 FALSE;
    }
    SI->Socket = s;
    SI->BytesSend = 0;
    SI->BytesRecv = 0;
    SocketArray[TotalSocket++] = SI;
    return TRUE;
}

void FreeSocketInformation(DWORD Index)
{
    LPSOCKET_INFORMATION SI = SocketArray[Index];
    closesocket(SI->Socket);
    GlobalFree(SI);
    for (DWORD i = Index; i < TotalSocket; i++)
    {
        SocketArray[i] = SocketArray[i + 1];
    }
    TotalSocket--;
}

int main()
{
    WSADATA wsadata;
    if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0)
    {
        printf("WSAStartup() 初始化失败!\n");
        WSACleanup();
        return -1;
    }

    SOCKET ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (ListenSocket == INVALID_SOCKET)
    {
        printf("WSASocket() failed with error %d\n", GetLastError());
        ::WSACleanup();
        return -1;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(27105);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);

    int errCode = bind(ListenSocket, (SOCKADDR*)&addr, sizeof(struct sockaddr_in));
    if (errCode == SOCKET_ERROR)
    {
        printf("bind() failed with error %d\n", WSAGetLastError());
        ::WSACleanup();
        return -1;
    }

    if (listen(ListenSocket, 2))
    {
        printf("listen() failed with error %d.\n", GetLastError());
        return -1;
    }

    ULONG NonBlock = 1;
    if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
    {
        printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
        closesocket(ListenSocket);
        ::WSACleanup();
        return -1;

    }
    printf("ioctlsocket() sucess\nrecv data... \n");

    CreateSocketInformation(ListenSocket);

    SOCKET AcceptSocket;
    FD_SET WriteSet, ReadSet;
    DWORD SendBytes, RecvBytes, Total = 0;
    while (true)
    {
        FD_ZERO(&ReadSet);
        FD_ZERO(&WriteSet);
        FD_SET(ListenSocket, &ReadSet);

        for (DWORD i = 0; i < TotalSocket; i++)
        {
            LPSOCKET_INFORMATION SockInfo = SocketArray[i];
            FD_SET(SockInfo->Socket, &ReadSet);
            FD_SET(SockInfo->Socket, &ReadSet);
        }

        Total = select(0, &ReadSet, &WriteSet, NULL, NULL);
        if (Total == SOCKET_ERROR)
        {
            printf("select() failed with error %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            ::WSACleanup();
            return -1;
        }

        for (DWORD i = 0; i < TotalSocket; i++)
        {
            LPSOCKET_INFORMATION SockInfo = SocketArray[i];
            if (FD_ISSET(SockInfo->Socket, &ReadSet))
            {
                if (SockInfo->Socket == ListenSocket)
                {
                    Total--;
                    AcceptSocket = accept(ListenSocket, NULL, NULL);
                    if (AcceptSocket != INVALID_SOCKET)
                    {
                        NonBlock = 1;
                        if (ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
                        {
                            printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
                            closesocket(ListenSocket);
                            ::WSACleanup();
                            return -1;
                        }
                        if (CreateSocketInformation(AcceptSocket) == FALSE)
                            return -1;
                    }
                    else
                    {
                        if (WSAGetLastError() != WSAEWOULDBLOCK)
                        {
                            printf("accept() failed with error %d", WSAGetLastError());
                            return -1;
                        }
                    }
                }
                else
                {
                    if (FD_ISSET(SockInfo->Socket, &ReadSet))
                    {
                        Total--;
                        memset(SockInfo->Buffer, ' ', DATA_BUFSIZE);
                        SockInfo->DataBuf.len = DATA_BUFSIZE;
                        SockInfo->DataBuf.buf = SockInfo->Buffer;
                        DWORD flags = 0;
                        if (WSARecv(SockInfo->Socket, &(SockInfo->DataBuf), 1, &RecvBytes, &flags, NULL, NULL) == SOCKET_ERROR)
                        {
                            if (WSAGetLastError() != WSAEWOULDBLOCK)
                            {
                                printf("WSARecv() failed with error %d\n", WSAGetLastError());
                                FreeSocketInformation(i);
                            }
                            continue;
                        }
                        else
                        {
                            SockInfo->BytesRecv = RecvBytes;
                            SockInfo->DataBuf.buf[RecvBytes] = '\0';
                            if (RecvBytes == 0)
                            {
                                FreeSocketInformation(i);
                            }
                            else
                            {
                                printf("recv : %s\n", SockInfo->DataBuf.buf);
                            }
                        }
                    }
                }
            }
            else
            {
                if (FD_ISSET(SockInfo->Socket, &WriteSet))
                {
                    Total--;
                    SockInfo->DataBuf.buf = SockInfo->Buffer + SockInfo->BytesSend;
                    SockInfo->DataBuf.len = SockInfo->BytesRecv - SockInfo->BytesSend;
                    if (SockInfo->DataBuf.len > 0)
                    {
                        if (WSASend(SockInfo->Socket, &(SockInfo->DataBuf), 1, &SendBytes, 0, NULL, NULL) == SOCKET_ERROR)
                        {
                            if (WSAGetLastError() != WSAEWOULDBLOCK)
                            {
                                printf("WSASend() failed with error %d\n", WSAGetLastError());
                                FreeSocketInformation(i);
                            }
                            continue;
                        }
                        else
                        {
                            SockInfo->BytesSend += SendBytes;
                            if (SockInfo->BytesRecv == SockInfo->BytesSend)
                            {
                                SockInfo->BytesRecv = 0;
                                SockInfo->BytesSend = 0;
                            }
                        }
                    }
                }
            }
        }
    }

    if (WSACleanup() == SOCKET_ERROR)
    {
        printf("WSACleanup() 出错!\n\n");
    }
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值