سؤال

أحاول كتابة غلاف تطبيق خادم ، كما أود مع أي تطبيق ، وقد بحثت عن أكثر من أسبوع للحصول على دليل أو برنامج تعليمي لائق على الأقل على مآخذ غير متزامنة (يجب أن يكون هذا الغلاف غير متزامن) وحتى الآن ما أستطيع هل هذا هو:

#ifndef _SERVER_H
#define _SERVER_H

#include "asynserv.h" // header file with the important lib includes
#include <map>

namespace Connections
{
    DWORD WINAPI MainThread(LPVOID lParam); // Main thread
    DWORD WINAPI DataThread(LPVOID lParam); // thread that will be created for each client
    struct ClientServer // struct to keep a server and a client pair.
    {
    public:
        struct Client* Client;
        class Server* Server;
    };
    struct Client // a struct wrapper to keep clients
    {
    public:
        Client(SOCKET Connection, int BufferSize, UINT ID);
        ~Client();
        SOCKET WorkerSocket;
        char Buffer[255];
        bool Connected;
        int RecvSize;
        UINT UID;
        void Send(char * Data);
        void Disconnect();
    };
    class Server
    {
    private:
        SOCKET WorkerSocket;
        SOCKADDR_IN EndPnt;
        UINT ID;
        int CBufferSize;
    public:
        Server(int Port, int Backlog, int BufferSize);
        ~Server();
        __event void ClientRecieved(Client* Clientr, char * RecData);
        bool Enabled;
        int Port;
        int Backlog;
        HWND ReqhWnd;
        std::map<UINT, Client*> ClientPool;
        void WaitForConnections(Server*);
        void WaitForData(Client*);
        void InvokeClientDC(UINT);
        void Startup();
        void Shutdown();
    };
}
#endif

server.cpp:

#include "Server.h"

namespace Connections
{
    void Server::Startup()
    {
        WSADATA wsa;
        WSAStartup(0x0202, &wsa);
        this->WorkerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        this->EndPnt.sin_addr.s_addr = ADDR_ANY;
        this->EndPnt.sin_family = AF_INET;
        this->EndPnt.sin_port = htons(this->Port);
        this->Enabled = true;
        this->ID = 0;
        bind(this->WorkerSocket, (SOCKADDR*)&this->EndPnt, sizeof(this->EndPnt));
        printf("[AsynServer]Bound..\n");
        listen(this->WorkerSocket, this->Backlog);
                CreateThread(NULL, NULL, &MainThread, this, NULL, NULL);
    }
    void Server::WaitForConnections(Server * Ser)
    {
        WSAEVENT Handler = WSA_INVALID_EVENT;
        while(Ser->Enabled)
        {
            Handler = WSACreateEvent();
            WSAEventSelect(Ser->WorkerSocket, Handler, FD_ACCEPT);
            WaitForSingleObject(Handler, INFINITE);
            SOCKET accptsock = accept(Ser->WorkerSocket, NULL, NULL);
            Client * NewClient = new Client(accptsock, 255, Ser->ID++);
            NewClient->Connected = true;
            printf("[AsynServer]Client connected.\n");
            ClientServer * OurStruct = new ClientServer();
            OurStruct->Server = Ser;
            OurStruct->Client = NewClient;
            CreateThread(NULL, NULL, &DataThread, OurStruct, NULL, NULL);
        }
    }
    void Server::WaitForData(Client * RClient)
    {
        WSAEVENT Tem = WSA_INVALID_EVENT;
        Tem = WSACreateEvent();
        WSAEventSelect(RClient->WorkerSocket, Tem, FD_READ);
        while(RClient->Connected)
        {
            WaitForSingleObject(Tem, INFINITE);
            RClient->RecvSize = recv(RClient->WorkerSocket, RClient->Buffer, 255, NULL);
            if(RClient->RecvSize > 0)
            {
                RClient->Buffer[RClient->RecvSize] = '\0';
                __raise this->ClientRecieved(RClient, RClient->Buffer);
                Sleep(50);
            }
        }
        return;
    }
    DWORD WINAPI MainThread(LPVOID lParam)
    {
        ((Server*)lParam)->WaitForConnections((Server*)lParam);
        return 0;
    }
    DWORD WINAPI DataThread(LPVOID lParam)
    {
        ClientServer * Sta = ((ClientServer*)lParam);
        Sta->Server->WaitForData(Sta->Client);
        return 0;
    }
}

الآن بعد إنشاء مثيل الخادم وإنشاء مؤشر الترابط الرئيسي ، يمكنني قبول العملاء في وقت واحد وقراءة البيانات التي يرسلونها ، ولكن بعد اتصالين يتخلف وحدة المعالجة المركزية حتى الاستخدام 100 ٪ .. أعتقد أن طريقتي غير صحيحة ، لذلك يمكن أن يكون سؤالي هو شخص ما أشر إلى عيب محتمل في الكود الخاص بي ، أو فقط أشر لي دليلًا لائقًا للمآخذ غير المتزامنة ، شريطة أن أكون قد بحثت بالفعل عن أكثر من أسبوع دون أي نتائج (ربما يأسني يمنعني من اختيار الكلمات الرئيسية الصحيحة: |). شكرًا مقدمًا وآسف على قطعة الكود الضخمة ، قلصتها طالما سمحت بها.

MFG ، SimpleButperfect.

هل كانت مفيدة؟

المحلول

1st Bug: In Server :: WaitforConnections تقوم بإنشاء Hevent (Handler = WsAcReateEvent ()) في كل مرة تنفّذ فيها حلقة أثناء تنفيذها دون تدميرها. حرك خلق hevent خارج الحلقة.

Bug 2nd: المخزن المؤقت الخاص بك هو 255 طويل (char) ولكنك تفعل هذا: rclient-> المخزن المؤقت [rclient-> recvsize] = ' 0' ؛ حيث يمكن أن يكون Rclient-> recvsize هو exaclty لحجم المخزن المؤقت الخاص بك - وهذا يعني أنك تجعل الفئة "تخزين العازلة".

آمل أن يساعد هذا. دومينيك

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top