簡體   English   中英

Winsock本地客戶端-服務器基准測試

[英]Winsock local client-server benchmarking

我打算評估這種簡單的客戶端-服務器程序的性能,該程序以測試客戶端發出固定數量的請求的方式進行設置;例如, 10000,然后查看服務器處理這些文件要花多長時間,然后再並行處理多個客戶端,因為它與線程一起運行。 現在我想知道如何編程嗎? (對不起,剛開始是Winsock)。 我還想知道這是否是線程的正確實現,如果不能,則可以改進什么,為什么。 提前致謝

測試服務器代碼;

服務器:

 #define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment(lib,"ws2_32.lib") //header file
#include <WinSock2.h>
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
SOCKET Connections[100];
int ConnectionCounter = 0;

void ClientHandlerThread(int index) //index = the index in the SOCKET Connections array
{
    char buffer[256]; //Buffer to receive and send out messages from/to the clients
    while (true)
    {
        recv(Connections[index], buffer, sizeof(buffer), NULL); //get message from client
        for (int i = 0; i < ConnectionCounter; i++) //For each client connection
        {
            if (i == index) //Don't send the chat message to the same user who sent it
                continue; //Skip user
            send(Connections[i], buffer, sizeof(buffer), NULL);//send the chat message to this client
        }
    }
}

int main()
{   
    std::cout << "\n\n\n\n\n                Server sucessfully turned on, awaiting for clients...\n\n\n\n\n";
    //Winsock Startup
    WSAData wsaData; 
    WORD DllVersion = MAKEWORD(2, 1);
    if (WSAStartup(DllVersion, &wsaData) != 0) //initialise winsock library, if WSAStartup returns anything other than 0, then that means an error has occured in the WinSock Startup.
    {
        MessageBoxA(NULL, "WinSock startup failed", "Error", MB_OK | MB_ICONERROR);
        return 0;
    }

    SOCKADDR_IN addr; //Address that we will bind our listening socket to
    int addrlen = sizeof(addr); //length of the address (required for accept call)
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //Broadcast locally, using inet_address funtion that converts to correct long format. 
    addr.sin_port = htons(1111); //Port
    addr.sin_family = AF_INET; //IPv4 Socket

    SOCKET sListen = socket(AF_INET, SOCK_STREAM, NULL); //Create socket to listen for new connections
    bind(sListen, (SOCKADDR*)&addr, sizeof(addr)); //Bind the address to the socket
    listen(sListen, SOMAXCONN); //Places sListen socket in a state in which it is listening for an incoming connection. Note:SOMAXCONN = Socket Oustanding Max Connections

    SOCKET newConnection; //Socket to hold the client's connection
    int ConnectionCounter = 0; //# of client connections
    for (int i = 0; i < 100; i++)
    {
        newConnection = accept(sListen, (SOCKADDR*)&addr, &addrlen); //Accept a new connection
        if (newConnection == 0) //If accepting the client connection failed
        {
            std::cout << "Failed to accept the client's connection." << std::endl;
        }
        else //If client connection properly accepted
        {
            std::cout << "\n\n\nClient Connected!\n\n" << std::endl;

    /*      char MOTD[256] = "Welcome! This is the Message of the Day."; //Create buffer with message of the day
            send(newConnection, MOTD, sizeof(MOTD), NULL); //Send MOTD buffer   */

            Connections[i] = newConnection; //Set socket in array to be the newest connection before creating the thread to handle this client's socket.
            ConnectionCounter += 1; //Incremenent total # of clients that have connected
            cout << "\nConnected Clients: ";
            cout << ConnectionCounter;

            CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientHandlerThread, (LPVOID)(i), NULL, NULL); //Create Thread to handle this client. The index in the socket array for this thread is the value (i).
        }
    }

    system("pause");
    return 0;
}

客戶:

    #define _WINSOCK_DEPRECATED_NO_WARNINGS
#pragma comment(lib,"ws2_32.lib") //Required for WinSock
#include <WinSock2.h> //For win sockets
#include <string> //For std::string
#include <iostream> //For std::cout, std::endl, std::cin.getline

SOCKET Connection;//This client's connection to the server

void ClientThread()
{
    char buffer[256]; //Create buffer to hold messages up to 256 characters
    while (true)
    {
        recv(Connection, buffer, sizeof(buffer), NULL); //receive buffer
        std::cout << buffer << std::endl; //print out buffer
    }
}

int main()
{
    //Winsock Startup
    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2, 1);
    if (WSAStartup(DllVersion, &wsaData) != 0)
    {
        MessageBoxA(NULL, "Winsock startup failed", "Error", MB_OK | MB_ICONERROR);
        return 0;
    }

    SOCKADDR_IN addr; //Address to be binded to our Connection socket
    int sizeofaddr = sizeof(addr); //Need sizeofaddr for the connect function
    addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //Address = localhost (this pc)
    addr.sin_port = htons(1111); //Port = 1111
    addr.sin_family = AF_INET; //IPv4 Socket

    Connection = socket(AF_INET, SOCK_STREAM, NULL); //Set Connection socket
    if (connect(Connection, (SOCKADDR*)&addr, sizeofaddr) != 0) //If we are unable to connect...
    {
        MessageBoxA(NULL, "Failed to Connect", "Error", MB_OK | MB_ICONERROR);
        return 0; //Failed to Connect
    }

    std::cout << "Connected!" << std::endl;
    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)ClientThread, NULL, NULL, NULL); //Create the client thread that will receive any data that the server sends.

    char buffer[256]; //256 char buffer to send message
    while (true)
    {
        std::cin.getline(buffer, sizeof(buffer)); //Get line if user presses enter and fill the buffer
        send(Connection, buffer, sizeof(buffer), NULL); //Send buffer
        Sleep(10);
    }

    return 0;
}

正如@JerryCoffin所說,使用“每個客戶端線程”模型會使線程之間的上下文切換過多,從而給服務器帶來負擔。 Nginx Web服務器等現代服務器使用異步非阻塞模型來實現可伸縮性。 我最近開發了這樣的架構。 為了更熟悉此模型,我為您提供了一些有用的鏈接。

從以下內容開始,以更熟悉該概念:

NGINX內部:我們如何設計性能和規模

您需要了解re-actorpro-actor設計模式。 您可以使用select()或類似的工具來實現它們。

示例:非阻塞I / O和select()

在boost,POCO和ACE之類的庫中也有一些不錯的實現。 就個人而言,我建議您看一下boost asio庫。 您可以在此處找到完整的文檔,教程和示例。

Boost.Asio

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM