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

📄 iocpclient.cpp

📁 这个是网络编程
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                    break;
                case 'c':               // Number of connections to make
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gConnectionCount = 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 'n':               // server address/name to connect to
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gServerAddr = argv[++i];
                    break;
                case 'o':               // overlapped count
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gOverlappedCount = atol(argv[++i]);
                    break;
                case 'p':               // local port
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gLocalPort = (USHORT) atoi(argv[++i]);
                    break;
                case 'r':               // Use the QOS packet scheduler
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gRateLimit = atol(argv[++i]);
                    break;
                case 't':               // Use TransmitFile instead of sends
                    gTransmitFile = TRUE;
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gFileSize = atol(argv[++i]);
                    break;
                case 'x':               // Number of sends to post total
                    if (i+1 >= argc)
                        usage(argv[0]);
                    gSendCount = atol(argv[++i]);
                    break;
                default:
                    usage(argv[0]);
                    break;
            }
        }
    }
}

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

    tick = GetTickCount();

    elapsed = (tick - gStartTime) / 1000;

    if (elapsed == 0)
	{
		printf("Bytes sent         : %lu\n", gBytesSent);
		printf("Bytes received     : %lu\n", gBytesRead);
		printf("Current Connections: %lu\n", gCurrentConnections);
        printf("Total Connections  : %lu\n", gTotalConnections);
        printf("Connections Refused: %lu\n", gConnectionRefused);
        return;
	}
	

    printf("\n");

    printf("Current Connections: %lu\n", gCurrentConnections);
    printf("Total Connections  : %lu\n", gTotalConnections);
    printf("Connections Refused: %lu\n", gConnectionRefused);


    // 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);

    InterlockedExchange(&gBytesSentLast, 0);
    InterlockedExchange(&gBytesReadLast, 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;

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

    if (rc == SOCKET_ERROR)
    {
        if (WSAGetLastError() != WSA_IO_PENDING)
        {
            fprintf(stderr, "PostRecv: WSARecv* failed: %d\n", WSAGetLastError());
            return SOCKET_ERROR;
        }
    }

    // Increment outstanding overlapped operations
    InterlockedIncrement(&sock->OutstandingOps);

    //printf("POST_READ: op %d\n", sock->OutstandingOps);

    return NO_ERROR;
}

//
// 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;

    sendobj->operation = OP_WRITE;

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

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

    if (rc == SOCKET_ERROR)
    {
        if (WSAGetLastError() != WSA_IO_PENDING)
        {
            fprintf(stderr, "PostSend: WSASend* failed: %d\n", WSAGetLastError());
            return SOCKET_ERROR;
        }
    }

    // Increment the outstanding operation count
    InterlockedIncrement(&sock->OutstandingOps);
    InterlockedDecrement(&sock->SendCount);

    //printf("POST_SEND: op %d\n", sock->OutstandingOps);

    return NO_ERROR;
}

//
// Function: PostConnect
// 
// Description:
//    Post an overlapped accept on a listening socket.
//
int PostConnect(SOCKET_OBJ *sock, BUFFER_OBJ *connobj)
{
    DWORD   bytes;
    int     rc;

    connobj->operation = OP_CONNECT;

    /*
    printf("Connecting to: ");
    PrintAddress((SOCKADDR *)&connobj->addr, connobj->addrlen);
    printf("\n");
    */

    rc = sock->lpfnConnectEx(
            sock->s,
            (SOCKADDR *)&connobj->addr,
            connobj->addrlen,
            connobj->buf,
            connobj->buflen,
           &bytes,
           &connobj->ol
            );
    if (rc == FALSE)
    {
        if (WSAGetLastError() != WSA_IO_PENDING)
        {
            fprintf(stderr, "PostConnect: ConnectEx failed: %d\n",
                    WSAGetLastError());
            return SOCKET_ERROR;
        }
    }

    // Increment the outstanding overlapped count for this socket
    InterlockedIncrement(&sock->OutstandingOps);

    //printf("POST_CONNECT: op %d\n", sock->OutstandingOps);

    return NO_ERROR;
}

//
// Function: PostTransmitFile
//
// Description:
//    Post a TransmitFile operation on the given socket connection.
//
int PostTransmitFile(SOCKET_OBJ *sock, BUFFER_OBJ *tfobj)
{
     int    rc;

     tfobj->operation = OP_TRANSMIT;
     tfobj->hFile = gTempFile;

     // Zero out the OVERLAPPED, the offset must be zero
     memset(&tfobj->ol, 0, sizeof(tfobj->ol));

     rc = sock->lpfnTransmitFile(
             sock->s,
             tfobj->hFile,
             0,
             0,
            &tfobj->ol,
             NULL,
             0
             );
     if (rc == FALSE)
     {
         if (WSAGetLastError() != WSA_IO_PENDING)
         {
             fprintf(stderr, "PostTransmitFile: TransmitFile failed: %d\n",
                     WSAGetLastError());
             return SOCKET_ERROR;
         }
     }

    // Increment the outstanding overlapped count for this socket
    InterlockedIncrement(&sock->OutstandingOps);
    InterlockedDecrement(&sock->SendCount);

    return NO_ERROR;
}

//
// Function: HandleIo
//
// Description:
//    This function handles the IO on a socket. In the event of a receive, the 
//    completed receive is posted again. For completed accepts, another AcceptEx
//    is posted. For completed sends, the buffer is freed.
//
int HandleIo(SOCKET_OBJ *sock, BUFFER_OBJ *buf, DWORD BytesTransfered, DWORD error)
{
    BUFFER_OBJ *recvobj=NULL,       // Used to post new receives on accepted connections
               *sendobj=NULL;       // Used to post new sends for data received
    BOOL        bCleanupSocket;
    int         rc,
                i;

    bCleanupSocket = FALSE;

    if (error != NO_ERROR)
    {
        // An error occured on a TCP socket, free the associated per I/O buffer
        // and see if there are any more outstanding operations. If so we must
        // wait until they are complete as well.
        //
        printf("error = %d\n", error);

        closesocket(sock->s);
        sock->s = INVALID_SOCKET;
       
        if (buf->operation == OP_CONNECT)
        {
            if (error == WSAECONNREFUSED)
            {
                InterlockedIncrement(&gConnectionRefused);
            }

            FreeBufferObj(buf);
			RemoveSocketObj(&gConnectionList, sock);
            FreeSocketObj(sock);

            if (gConnectionList == NULL)
                return 0;
        }
        else
        {
			FreeBufferObj(buf);
            if (sock->OutstandingOps == 0)
            {
                RemoveSocketObj(&gConnectionList, sock);
                FreeSocketObj(sock);
            }
        }
        return SOCKET_ERROR;
    }
    else
    {
        if (buf->operation == OP_CONNECT)
        {
            int     optval=1;

            // Update counters
            InterlockedIncrement(&gCurrentConnections);
            InterlockedIncrement(&gTotalConnections);
            InterlockedExchangeAdd(&gBytesSent, BytesTransfered);
            InterlockedExchangeAdd(&gBytesSentLast, BytesTransfered);

            // Need to update the socket context in order to use the shutdown API
            rc = setsockopt(
                    sock->s,
                    SOL_SOCKET,
                    SO_UPDATE_CONNECT_CONTEXT,
                    (char *)&optval,
                    sizeof(optval)
                    );
            if (rc == SOCKET_ERROR)
            {
                fprintf(stderr, "setsockopt: SO_UPDATE_CONNECT_CONTEXT failed: %d\n",
                        WSAGetLastError());
            }

            sock->bConnected = TRUE;

            // Post the specified number of receives on the succeeded connection
            for(i=0; i < gOverlappedCount ;i++)
            {
                recvobj = GetBufferObj(gBufferSize);

                if (PostRecv(sock, recvobj) != NO_ERROR)
                {
                    FreeBufferObj(recvobj);
                    bCleanupSocket = TRUE;
                    break;
                }
            }

            for(i=0; ((i < gOverlappedCount) && (!bCleanupSocket)) ;i++)
            {
                sendobj = GetBufferObj(gBufferSize);

                if (gTransmitFile)
                {
                    rc = PostTransmitFile(sock, sendobj);
                }
                else
                {
                    rc = PostSend(sock, sendobj);
                }
                if (rc != NO_ERROR)
                {
                    FreeBufferObj(sendobj);
                    bCleanupSocket = TRUE;
                    break;
                }
                if (sock->SendCount == 0)
                    break;
            }

            FreeBufferObj(buf);
        }
        else if (buf->operation == OP_READ)
        {
            //
            // Receive completed successfully
            //
            if ((BytesTransfered > 0) && (!sock->bClosing))
            {
                InterlockedExchangeAdd(&gBytesRead, BytesTransfered);
                InterlockedExchangeAdd(&gBytesReadLast, BytesTransfered);

                if (PostRecv(sock, buf) != NO_ERROR)
                {
                    // In the event the recv fails, clean up the connection
                    FreeBufferObj(buf);
                    bCleanupSocket = TRUE;
                }
            }
            else
            {
                // Graceful close - the receive returned 0 bytes read
                sock->bClosing = TRUE;

                // Free the receive buffer
                FreeBufferObj(buf);

                //printf("zero byte read\n");
            }
        }
        else if (buf->operation == OP_WRITE)
        {
            // Update the counters
            InterlockedExchangeAdd(&gBytesSent, BytesTransfered);
            InterlockedExchangeAdd(&gBytesSentLast, BytesTransfered);

            // If there are sends to be made, call PostSend again
            EnterCriticalSection(&sock->SockCritSec);
            if (gRateLimit == -1)
            {
                // If no rate limiting just repost the send
                if (sock->SendCount > 0)
                {
                    rc = PostSend(sock, buf);
                    if (rc != NO_ERROR)
                    {
                        bCleanupSocket = TRUE;
                    }
                }
                else
                {
                    // Otherwise, shutdown the socket
                    if (shutdown(sock->s, SD_SEND) == SOCKET_ERROR)
                    {
                        printf("shutdown failed: %d (handle = 0x%p\n", WSAGetLastError(), sock->s);
                    }
                    FreeBufferObj(buf);
                }
            }
            else
            {
                // If rate limiting is turned on then save off the send object for
                // sending by the rate thread.
                //
                if (sock->SendCount > 0)
                {
                    buf->next = sock->Repost;
                    sock->Repost = buf;
                }
                else
                {
                    // Otherwise, shutdown the socket
                    if (shutdown(sock->s, SD_SEND) == SOCKET_ERROR)
                    {
                        printf("shutdown failed: %d (handle = 0x%p\n", WSAGetLastError(), sock->s);

⌨️ 快捷键说明

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