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

📄 bserver.cpp

📁 这个是网络编程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            ReleaseSemaphore(ConnObj->hRecvSema, 1, NULL);

            if (rc == 0)
            {
                break;
            }
        }
    }
    else if (gProtocol == IPPROTO_TCP)
    {
        // loop until the connection is closed or is aborted/terminated
        while (1)
        {
            // Allocate the buffer for stream send/recv
            BuffObj = GetBufferObj(gBufferSize);

            rc = recv(
                    ConnObj->s, 
                    BuffObj->buf, 
                    BuffObj->buflen, 
                    0);
            BuffObj->buflen = rc;

            // Queue the receive buffer for sending and signal the send thread
            EnqueueBufferObj(ConnObj, BuffObj);

            ReleaseSemaphore(ConnObj->hRecvSema, 1, NULL);

            if (rc == 0 || rc == SOCKET_ERROR)
            {
                break;
            }
            else if (rc != SOCKET_ERROR)
            {
                // Increment the statistics
                InterlockedExchangeAdd(&gBytesRead, rc);
                InterlockedExchangeAdd(&gBytesReadLast, rc);
            }

        }

    }

    ExitThread(0);
    return 0;
}

// 
// Function: SendThread
//
// Description:
//    This is the send thread started for each client connection.
//    This thread waits for the semaphore to be signaled indicating that
//    the receive thread has queued a buffer for sending.
//
DWORD WINAPI SendThread(LPVOID lpParam)
{
    CONNECTION_OBJ *ConnObj=NULL;
    BUFFER_OBJ     *BuffObj=NULL;
    int             rc,
                    nleft,
                    idx;


    // Retrieve the connection object
    ConnObj = (CONNECTION_OBJ *)lpParam;

    while (1)
    {
        // Wait for the receive thread to signal us
        rc = WaitForSingleObject(ConnObj->hRecvSema, INFINITE);
        if (rc == WAIT_FAILED || rc == WAIT_TIMEOUT)
        {
            fprintf(stderr, "WaitForSingleObject failed: %d\n", GetLastError());
            ExitProcess(-1);
        }

        // Retrieve the first buffer from this connection's queue
        BuffObj = DequeueBufferObj(ConnObj);

        //
        // If the this receive by the receive thread indicated zero bytes then
        // the connection has been gracefully closed. Otherwise, if an error
        // was indicated then the connection was aborted.
        //
        if ((gProtocol == IPPROTO_TCP ) && ((BuffObj->buflen == 0) || (BuffObj->buflen == SOCKET_ERROR)))
        {
            FreeBufferObj(BuffObj);
            BuffObj = NULL;
            break;
        }

        if (gProtocol == IPPROTO_UDP)
        {
            // For UDP we send the packet back to the source address
            rc = sendto(
                    ConnObj->s,
                    BuffObj->buf,
                    BuffObj->buflen,
                    0,
                    (SOCKADDR *)&BuffObj->addr,
                    BuffObj->addrlen
                    );
            if (BuffObj->buflen == 0)
            {
                FreeBufferObj(BuffObj);
                BuffObj = NULL;
                break;
            }
        }
        else if (gProtocol == IPPROTO_TCP)
        {
            // Otherwise send the buffer on the connection socket
            nleft = BuffObj->buflen;
            idx = 0;

            while (nleft > 0)
            {
                rc = send(
                        ConnObj->s,
                       &BuffObj->buf[idx],
                        nleft,
                        0
                        );
                if (rc == SOCKET_ERROR)
                {
                    break;
                }
                else
                {
                    nleft -= rc;
                    idx += rc;
                }
            }
        }
        if (rc == SOCKET_ERROR)
        {
            printf("SendThread: send(to) failed: %d\n", WSAGetLastError());
            break;
        }
        else if (rc > 0)
        {
            // Increment the statistics
            InterlockedExchangeAdd(&gBytesSent, rc);
            InterlockedExchangeAdd(&gBytesSentLast, rc);
        }

        FreeBufferObj(BuffObj);
        BuffObj = NULL;
    }

    // Close the connection's socket
    closesocket(ConnObj->s);

    FreeConnectionObj(ConnObj);

    ExitThread(0);
    return 0;
}

//
// Funtion: ServerListenThread
//
// Description:
//    This function is spawned for each listening or receive thread
//    depending on whether the server is started for UDP or TCP. In
//    reality there will only be two server threads, one for IPv4
//    and one for IPv6.
//
DWORD WINAPI ServerListenThread(LPVOID lpParam)
{
    CONNECTION_OBJ *ConnObj=NULL;
    HANDLE          hThread = NULL;
    SOCKET          s;
    int             rc;

    s = (SOCKET) lpParam;

    if (gProtocol == IPPROTO_UDP)
    {
        // If we're UDP we don't have any "connections" to handle. we just have to
        // receive UDP packets and send them back. Hence we only need 1 receiver
        // thread and 1 sender thread for the whole thing.
        //
        ConnObj = GetConnectionObj(s);

        hThread = CreateThread(NULL, 0, ReceiveThread, (LPVOID)ConnObj, 0, NULL);
        if (hThread == NULL)
        {
            fprintf(stderr, "ServerListenThread: CreateThread failed: %d\n", GetLastError());
            ExitThread(-1);
        }

        SendThread((LPVOID)ConnObj);
    }
    else if (gProtocol == IPPROTO_TCP)
    {
        SOCKADDR_STORAGE saAccept;      // client address
        SOCKET           ns;            // client socket
        int              acceptlen = sizeof(SOCKADDR_STORAGE);

        rc = listen(s, 200);
        if (rc == SOCKET_ERROR)
        {
            fprintf(stderr, "listen failed: %d\n", WSAGetLastError());
            ExitThread(-1);
        }

        while (1)
        {
            // Wait for an incoming client connection
            ns = accept(s, (SOCKADDR *)&saAccept, &acceptlen);
            if (ns == INVALID_SOCKET)
            {
                fprintf(stderr, "accept failed: %d\n", WSAGetLastError());
                return -1;
            }

            InterlockedIncrement(&gConnectedClients);

            /*
            printf("Accepted connection from: ");
            PrintAddress((SOCKADDR *)&saAccept, acceptlen); 
            printf("\n");
            */

            // Allocate a connection object for this client
            ConnObj = GetConnectionObj(ns);

            // Create a receiver thread for this connection
            hThread = CreateThread(NULL, 0, ReceiveThread, (LPVOID)ConnObj, 0, NULL);
            if (hThread == NULL)
            {
                fprintf(stderr, "CreateThread failed: %d\n", GetLastError());
                ExitThread(-1);
            }
            CloseHandle(hThread);

            // Create a sender thread for this connection
            hThread = CreateThread(NULL, 0, SendThread, (LPVOID)ConnObj, 0, NULL);
            if (hThread == NULL)
            {
                fprintf(stderr, "CreateThread failed: %d\n", GetLastError());
                ExitThread(-1);
            }
            CloseHandle(hThread);
        }
    }

    closesocket(s);

    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           s[MAX_LISTEN_SOCKETS];
    HANDLE           threads[MAX_LISTEN_SOCKETS];
    int              rc,
                     listencount=0,
                     i;
    struct addrinfo *res=NULL,
                    *ptr=NULL;

    ValidateArgs(argc, argv);

    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
        fprintf(stderr, "unable to load Winsock!\n");
        return -1;
    }

    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)
    {
        if (listencount > MAX_LISTEN_SOCKETS)
        {
            fprintf(stderr, "Exceeded maximum listening sockets allowed\n");
            return -1;
        }

        PrintAddress(ptr->ai_addr, ptr->ai_addrlen); printf("\n");

        // create the socket
        s[listencount] = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);
        if (s[listencount] == INVALID_SOCKET)
        {
            fprintf(stderr,"socket failed: %d\n", WSAGetLastError());
            return -1;
        }

        // bind the socket to a local address and port
        rc = bind(s[listencount], ptr->ai_addr, ptr->ai_addrlen);
        if (rc == SOCKET_ERROR)
        {
            fprintf(stderr, "bind failed: %d\n", WSAGetLastError());
            return -1;
        }

        // Create a listen thread for each local address to listen on
        threads[listencount] = CreateThread(
                NULL, 
                0, 
                ServerListenThread, 
                (LPVOID)s[listencount],
                0,
                NULL
                );
        if (threads[listencount] == NULL)
        {
            fprintf(stderr, "CreateThread failed: %d\n", GetLastError());
            return -1;
        }

        listencount++;
        ptr = ptr->ai_next;
    }

    gStartTime = gStartTimeLast = GetTickCount();

    // free the addrinfo structure for the 'bind' address
    freeaddrinfo(res);

    while (1)
    {
        // Wait for the listening threads to exit, also print out statistics
        // when the wait times out
        rc = WaitForMultipleObjects(listencount, threads, TRUE, 5000);
        if (rc == WAIT_FAILED)
        {
            fprintf(stderr, "WaitForMultipleObjects failed: %d\n", GetLastError());
            return -1;
        }
        else if (rc == WAIT_TIMEOUT)
        {
            ULONG       bps, tick, elapsed;

            tick = GetTickCount();

            elapsed = (tick - gStartTime) / 1000;


            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;

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

            printf("Current Connections: %lu\n", gConnectedClients);

            gStartTimeLast = tick;
        }
        else
        {
            break;
        }
    }
    // Close the thread handles opened
    for (i=0; i < listencount ;i++)
    {
        CloseHandle(threads[i]);
    }

    WSACleanup();
    return 0;
}

⌨️ 快捷键说明

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