Winsock本地客户服务器基准测试

Winsock local client-server benchmarking

本文关键字:服务器 基准测试 客户服务 客户 Winsock      更新时间:2023-10-16

我正在绑扎以评估这个简单的客户端服务器程序的性能,以测试客户端提出固定数量的请求的方式,例如;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 << "nnnnn                Server sucessfully turned on, awaiting for clients...nnnnn";
    //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 << "nnnClient Connected!nn" << 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 Web服务器(的现代服务器使用异步非阻滞模型来达到可扩展性。我最近开发了这样的建筑。为了更熟悉此模型,我为您提供了一些有用的链接。

从以下内容开始,以更熟悉该概念:

nginx内部:我们如何为性能设计&amp;比例

您需要知道 re-actor pro-actor 设计模式。您可以使用Select((或类似设施实现它们。

示例:非块I/O和select((

在Boost,Poco和Ace等库中也有一些很好的实现。就个人而言,我建议您查看Boost Asio库。您可以在此处找到完整的文档,教程和示例。

boost.asio