-1

新しいスレッドで着信接続の各要求処理を整理するのに助けが必要です (コードはこのトピックの最後にあります)。

各リクエストを処理してキューを手動で( boost/threadpool を使用せずに)整理する方法がまったくわかりませんか?ブーストなどを使用しないでこのような問題を解決するにはどうすればよいですか?

手動でやりたいのですが、次の方法がわかりません。

  • 新しい接続ごとにリッスンする
  • 新しい接続がある場合は、新しいスレッドで処理を送信します
  • スレッドが処理プロセスを終了したら、このスレッドを閉じます

私はwhile(true);でそのようなことをしようとしました。しかし、各 HTTP リクエストを処理するためにリクエスト キューを適切に編成する方法がわかりません。

私のコードは次のとおりです。

#include <iostream>
#include <Windows.h>

#pragma comment(lib, "Ws2_32.lib")

typedef struct Header
{
friend struct Net;

private:
    WORD wsa_version;
    WSAData wsa_data;

    SOCKET sock;
    SOCKADDR_IN service;

    char *ip;
    unsigned short port;

public:
    Header(void)
    {
        wsa_version = 0x202;

        ip = "0x7f.0.0.1";
        port = 0x51;

        service.sin_family = AF_INET;
        service.sin_addr.s_addr = inet_addr(ip);
        service.sin_port = htons(port);
    }

} Header;

typedef struct Net
{
private:
    int result;

    HANDLE thrd;
    DWORD exit_code;

    void WSAInit(WSAData *data, WORD *wsa_version)
    {
        result = WSAStartup(*wsa_version, &(*data));

        if(result != NO_ERROR)
        {
            std::cout << "WSAStartup() failed with the error: " << result << std::endl;
        }
        else
        {
            std::cout << (*data).szDescription << " " << (*data).szSystemStatus << std::endl;
        }
    }

    void SocketInit(SOCKET *my_socket)
    {
        (*my_socket) = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

        if((*my_socket) == INVALID_SOCKET)
        {
            std::cout << "Socket initialization failed with the error: " << WSAGetLastError() << std::endl;
            WSACleanup();
        }
        else
        {
            std::cout << "Socket initialization successful!" << std::endl;
        }
    }

    void SocketBind(SOCKET *my_socket, SOCKADDR_IN *service)
    {
        result = bind((*my_socket), (SOCKADDR*)&(*service), sizeof(*service));

        if(result == SOCKET_ERROR)
        {
            std::cout << "Socket binding failed with the error: " << WSAGetLastError() << std::endl;
            closesocket((*my_socket));
            WSACleanup();
        }
        else
        {
            std::cout << "Socket binding successful!" << std::endl;
        }

        result = listen(*my_socket, SOMAXCONN);

        if(result == SOCKET_ERROR)
        {
            std::cout << "Socket listening failed with the error: " << WSAGetLastError() << std::endl;
        }
        else
        {
            std::cout << "Listening to the socket..." << std::endl;
        }
    }

    void SocketAccept(SOCKET *my_socket)
    {
        SOCKET sock_accept = accept((*my_socket), 0, 0);

        if(sock_accept == INVALID_SOCKET)
        {
            std::cout << "Accept failed with the error: " << WSAGetLastError() << std::endl;
            closesocket(*my_socket);
            WSACleanup();
        }
        else
        {
            std::cout << "Client socket connected!" << std::endl;

            thrd = CreateThread(NULL, 0, &Net::Threading, &sock_accept, 0, NULL);
        }
    }

    static void HandleRequest(char response[], int length)
    {
        std::cout << std::endl;

        for(int i = 0; i < length; i++)
        {
            std::cout << response[i];
        }

        std::cout << std::endl;
    }

    static DWORD WINAPI Threading(LPVOID lpParam)
    {
        SOCKET *my_socket = (SOCKET*)lpParam;

        char data[0x400];
        int result = recv((*my_socket), data, sizeof(data), 0);
        HandleRequest(data, result);
        char *response = "HTTP/1.1 200 OK\r\nServer: Amegas.sys-IS/1.0\r\nContent-type: text/html\r\nSet-Cookie: ASD643DUQE7423HFDG; path=/\r\nCache-control: private\r\n\r\n<h1>Hello World!</h1>\r\n\r\n";
        result = send((*my_socket), response, (int)strlen(response), 0);

        if(result == SOCKET_ERROR)
        {
            std::cout << "Sending data via socket failed with the error: " << WSAGetLastError() << std::endl;
            closesocket((*my_socket));
            WSACleanup();
        }
        else
        {
            result = shutdown((*my_socket), 2);
        }

        return 0;
    }

public:
    Net(void)
    {
        Header *obj_h = new Header();

        WSAInit(&obj_h->wsa_data, &obj_h->wsa_version);

        SocketInit(&obj_h->sock);
        SocketBind(&obj_h->sock, &obj_h->service);

        SocketAccept(&obj_h->sock);

        delete obj_h;
    }
} Net;

int main(void)
{
    Net *obj_net = new Net();

    delete obj_net;

    return 0;
}
4

1 に答える 1

2

OS が accept() キューイングを処理します - あまり心配する必要はありません。単純な同期サーバーは、次のように実行される傾向があります。

socket listeningSocket:=socket.create;
listeningSocket.bind('0.0.0.0',80);  // address/port
listeningSocket.listen;

while(true){
  socket serverClientSocket=accept(listeningSocket);
  createThread(&serverClientThread,serverClientSocket);
}

void serverClientThread(void *param)
{
  inBuffer char[256];
  socket myServerClientSocket=(socket)param;
  while(true){
     int bytesRx=recv(myServerClientSocket,&inBuffer,size(inBuffer));
     if (bytesRx>0){
        if doSomethingWith(&inBuffer,bytesRx) // not necessarily size(inBuffer) bytes!!
        {
           send(myServerClientSocket,"Reply from server\r\n");
        }

     }
     else
       return; // on error or connection closed
  }
}

リッスンしている 1 つのスレッド (コンソール アプリのメイン スレッドの場合もあります) は、accept() ループを永遠に実行します。個別の serverClientThread インスタンスは、クライアントが切断されるか、その他のエラーが発生するまで実行されます。

于 2012-04-29T22:09:41.270 に答える