⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iocpserver.cpp

📁 这个是网络编程
💻 CPP
📖 第 1 页 / 共 4 页
字号:

//
// Function: RemovePendingAccept
//
// Description:
//    Removes the indicated accept buffer object from the list of pending
//    accepts in the listening object.
//
void RemovePendingAccept(LISTEN_OBJ *listenobj, BUFFER_OBJ *obj)
{
    BUFFER_OBJ *ptr=NULL, *prev=NULL;

    EnterCriticalSection(&listenobj->ListenCritSec);
   
    // Search list until we find the object
    ptr = listenobj->PendingAccepts;
    while ( (ptr) && (ptr != obj) )
    {
        prev = ptr;
        ptr  = ptr->next;
    }
    if (prev)
    {
        // Object is somewhere after the first entry
        prev->next = obj->next;
    }
    else
    {
        // Object is the first entry
        listenobj->PendingAccepts = obj->next;
    }

    LeaveCriticalSection(&listenobj->ListenCritSec);
}

//
// Function: GetBufferObj
// 
// Description:
//    Allocate a BUFFER_OBJ. A lookaside list is maintained to increase performance
//    as these objects are allocated frequently.
//
BUFFER_OBJ *GetBufferObj(int buflen)
{
    BUFFER_OBJ *newobj=NULL;

    EnterCriticalSection(&gBufferListCs);
    if (gFreeBufferList == NULL)
    {
        // Allocate the object
        newobj = (BUFFER_OBJ *)HeapAlloc(
                GetProcessHeap(), 
                HEAP_ZERO_MEMORY, 
                sizeof(BUFFER_OBJ) + (sizeof(BYTE) * buflen)
                );
        if (newobj == NULL)
        {
            fprintf(stderr, "GetBufferObj: HeapAlloc failed: %d\n", GetLastError());
        }
    }
    else
    {
        newobj          = gFreeBufferList;
        gFreeBufferList = newobj->next;
        newobj->next    = NULL;
    }
    LeaveCriticalSection(&gBufferListCs);
    
    if (newobj)
    {
        newobj->buf     = (char *)(((char *)newobj) + sizeof(BUFFER_OBJ));
        newobj->buflen  = buflen;
        newobj->addrlen = sizeof(newobj->addr);
    }

    return newobj;
}

//
// Function: FreeBufferObj
// 
// Description:
//    Free the buffer object. This adds the object to the free lookaside list.
//
void FreeBufferObj(BUFFER_OBJ *obj)
{
    EnterCriticalSection(&gBufferListCs);

    memset(obj, 0, sizeof(BUFFER_OBJ) + gBufferSize);
    obj->next = gFreeBufferList;
    gFreeBufferList = obj;

    LeaveCriticalSection(&gBufferListCs);
}

//
// Function: GetSocketObj
//
// Description:
//    Allocate a socket object and initialize its members. A socket object is
//    allocated for each socket created (either by socket or accept).
//    Socket objects are returned from a lookaside list if available. Otherwise,
//    a new object is allocated.
//
SOCKET_OBJ *GetSocketObj(SOCKET s, int af)
{
    SOCKET_OBJ  *sockobj=NULL;

    EnterCriticalSection(&gSocketListCs);
    if (gFreeSocketList == NULL)
    {
        sockobj = (SOCKET_OBJ *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_OBJ));
        if (sockobj == NULL)
        {
            fprintf(stderr, "GetSocketObj: HeapAlloc failed: %d\n", GetLastError());
        }
        else
        {
            InitializeCriticalSection(&sockobj->SockCritSec);
        }
    }
    else
    {
        sockobj         = gFreeSocketList;
        gFreeSocketList = sockobj->next;
        sockobj->next   = NULL;
    }
    LeaveCriticalSection(&gSocketListCs);

    // Initialize the members
    if (sockobj)
    {
        sockobj->s  = s;
        sockobj->af = af;
    }

    return sockobj;
}

//
// Function: FreeSocketObj
//
// Description:
//    Frees a socket object. The object is added to the lookaside list.
//
void FreeSocketObj(SOCKET_OBJ *obj)
{
    CRITICAL_SECTION cstmp;
    BUFFER_OBJ      *ptr=NULL;

    // Close the socket if it hasn't already been closed
    if (obj->s != INVALID_SOCKET)
    {
        printf("FreeSocketObj: closing socket\n");
        closesocket(obj->s);
        obj->s = INVALID_SOCKET;
    }

    EnterCriticalSection(&gSocketListCs);

    cstmp = obj->SockCritSec;
    memset(obj, 0, sizeof(SOCKET_OBJ));
    obj->SockCritSec = cstmp;

    obj->next = gFreeSocketList;
    gFreeSocketList = obj;

    LeaveCriticalSection(&gSocketListCs);
}

//
// Function: ValidateArgs
//
// Description:
//      Parses the command line arguments and sets up some global 
//      variables.
//
void ValidateArgs(int argc, char **argv)
{
    int     i;

    for(i=1; i < argc ;i++)
    {
        if (((argv[i][0] != '/') && (argv[i][0] != '-')) || (strlen(argv[i]) < 2))
            usage(argv[0]);
        else
        {
            switch (tolower(argv[i][1]))
            {
                case 'a':               // address family - IPv4 or IPv6
                    if (i+1 >= argc)
                        usage(argv[0]);
                    if (argv[i+1][0] == '4')
                        gAddressFamily = AF_INET;
                    else if (argv[i+1][0] == '6')
                        gAddressFamily = AF_INET6;
                    else
                        usage(argv[0]);
                    i++;
                    break;
                case 'b':               // buffer size for send/recv
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gBufferSize = atol(argv[++i]);
                    break;
                case 'e':               // endpoint - port number
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gBindPort = argv[++i];
                    break;
                case 'l':               // local address for binding
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gBindAddr = argv[++i];
                    break;
                case 'o':               // overlapped count
                    if (i+1 >= argc)
                        usage(argv[0]);
                    if (strlen(argv[i]) == 2)       // Overlapped accept initial count
                    {
                        gInitialAccepts = atol(argv[++i]);
                    }
                    else if (strlen(argv[i]) == 3)
                    {
                        if (tolower(argv[i][2]) == 'a')
                            gMaxAccepts = atol(argv[++i]);
                        else if (tolower(argv[i][2]) == 's')
                            gMaxSends = atol(argv[++i]);
                        else if (tolower(argv[i][2]) == 'r')
                            gMaxReceives = atol(argv[++i]);
                        else
                            usage(argv[0]);
                    }
                    else
                    {
                        usage(argv[0]);
                    }
                    break;
                default:
                    usage(argv[0]);
                    break;
            }
        }
    }
}

//
// Function: PrintStatistics
//
// Description:
//    Print the send/recv statistics for the server
//
void PrintStatistics()
{
    ULONG       bps, tick, elapsed, cps;

    tick = GetTickCount();

    elapsed = (tick - gStartTime) / 1000;

    if (elapsed == 0)
        return;

    printf("\n");

    // Calculate average bytes per second
    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;

    // Calculate bytes per second over the last X seconds
    bps = gBytesSentLast / elapsed;
    printf("Current BPS sent: %lu\n", bps);

    bps = gBytesReadLast / elapsed;
    printf("Current BPS read: %lu\n", bps);

    cps = gConnectionsLast / elapsed;
    printf("Current conns/sec: %lu\n", cps);
    
    printf("Total connections: %lu\n", gConnections);

    InterlockedExchange(&gBytesSentLast, 0);
    InterlockedExchange(&gBytesReadLast, 0);
    InterlockedExchange(&gConnectionsLast, 0);

    gStartTimeLast = tick;
}

//
// Function: PostRecv
// 
// Description: 
//    Post an overlapped receive operation on the socket.
//
int PostRecv(SOCKET_OBJ *sock, BUFFER_OBJ *recvobj)
{
    WSABUF  wbuf;
    DWORD   bytes,
            flags;
    int     rc;

    recvobj->operation = OP_READ;

    wbuf.buf = recvobj->buf;
    wbuf.len = recvobj->buflen;

    flags = 0;

    EnterCriticalSection(&sock->SockCritSec);

    rc = WSARecv(
            sock->s,
           &wbuf,
            1,
           &bytes,
           &flags,
           &recvobj->ol,
            NULL
            );

    if (rc == SOCKET_ERROR)
    {
        rc = NO_ERROR;
        if (WSAGetLastError() != WSA_IO_PENDING)
        {
            dbgprint("PostRecv: WSARecv* failed: %d\n", WSAGetLastError());
            rc = SOCKET_ERROR;
        }
    }
    if (rc == NO_ERROR)
    {
        // Increment outstanding overlapped operations
        InterlockedIncrement(&sock->OutstandingRecv);
    }

    LeaveCriticalSection(&sock->SockCritSec);

    return rc;
}

//
// Function: PostSend
// 
// Description:
//    Post an overlapped send operation on the socket.
//
int PostSend(SOCKET_OBJ *sock, BUFFER_OBJ *sendobj)
{
    WSABUF  wbuf;
    DWORD   bytes;
    int     rc, err;

    sendobj->operation = OP_WRITE;

    wbuf.buf = sendobj->buf;
    wbuf.len = sendobj->buflen;

    EnterCriticalSection(&sock->SockCritSec);

    rc = WSASend(
            sock->s,
           &wbuf,
            1,
           &bytes,
            0,
           &sendobj->ol,
            NULL
            );

    if (rc == SOCKET_ERROR)
    {
        rc = NO_ERROR;
        if ((err = WSAGetLastError()) != WSA_IO_PENDING)
        {
            if (err == WSAENOBUFS)
                DebugBreak();

            dbgprint("PostSend: WSASend* failed: %d [internal = %d]\n", WSAGetLastError(), sendobj->ol.Internal);
            rc = SOCKET_ERROR;
        }
    }
    if (rc == NO_ERROR)
    {
        // Increment the outstanding operation count
        InterlockedIncrement(&sock->OutstandingSend);

        InterlockedIncrement(&gOutstandingSends);
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -