2012-06-25 11 views
1

幾個星期前我已經開始Windows套接字編程。C++中面向對象的客戶端套接字應用程序設計

到目前爲止,我已經創建了一個C風格的客戶端應用程序(基於IOCP),它與VC++ 2010中的網絡硬件設備進行通信。應用程序通過LAN或串行端口與設備(作爲服務器)異步通信:

  • 創建插座/或處理,以串行端口
  • 連接到服務器類型爲std
  • 生成命令::載體(例如,登錄命令)
  • 經由套接字或串行端口發送命令
  • 接收通過插座或串口
  • 從服務器

現在,我想使我現有的客戶端應用程序更加面向對象的,我已經想出了下面的類層次結構

  • 斷開(PARAMS響應省略):

    class IClient 
    { 
    public: 
        virtual bool Connect() = 0; 
        virtual bool Disconnect() = 0; 
        virtual bool Send() = 0; 
        virtual bool Receive() = 0; 
        ... 
    }; 
    
    class Client : public IClient 
    { 
    public: 
        Client(); 
        virtual ~Client(); 
    
        virtual bool Connect() = 0; 
        virtual bool Disconnect() = 0; 
        virtual bool Send() = 0; 
        virtual bool Receive() = 0; 
        ... 
    
    private: 
        std::string m_strConnectionSettings; // IP address, port number etc 
    }; 
    
    class SerialClient : public Client 
    { 
    public: 
        bool Connect() 
        { 
         ... 
         m_hPort = CreateFile(_T("COM3"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 
         ... 
        } 
    
        bool Disconnect() 
        { 
         ... 
         CloseHandle(m_hPort); 
         ... 
        } 
    
        bool Send() 
        { 
         ... 
         WriteFile(m_hPort, (LPCVOID)(&vecByteData[0]), vecByteData.size(), &dwNumberOfBytesWritten, NULL); 
         ... 
        } 
    
        bool Receive() 
        { 
         ... 
         ReadFile(m_hPort, (LPVOID)&vecBuffer[0], vecBuffer.size(), &dwNumberOfBytesRead, NULL); 
         ... 
        } 
        ... 
    
    private: 
        HANDLE m_hPort; // Handle returned by CreateFile(). 
        DCM m_dcb; 
    }; 
    
    class SocketClient : public Client 
    { 
    public: 
        SocketClient(); 
        virtual ~SocketClient(); 
    
        virtual bool Connect() = 0; 
        virtual bool Disconnect() = 0; 
        virtual bool Send() = 0; 
        virtual bool Receive() = 0; 
        ... 
    
    private: 
        SOCKET m_socket; // Handle returned by WSASocket(). 
    }; 
    
    class TcpClient : public SocketClient 
    { 
    public: 
        TcpClient(); 
        ~TcpClient(); 
    
        bool Connect() 
        { 
         ... 
         WSAConnect(m_sock, (LPSOCKADDR)&server, sizeof(server), NULL, NULL, NULL, NULL); 
         ... 
        } 
    
        bool Disconnect() 
        { 
         ... 
         closesocket(m_sock); 
         ... 
        } 
    
        bool Send() 
        { 
         ... 
         WSASend(m_sock, ...); 
         ... 
        } 
    
        bool Receive() 
        { 
         ... 
         WSARecv(m_sock, ...); 
         ... 
        } 
        ... 
    }; 
    
    class UdpClient : public SocketClient 
    { 
    public: 
        UdpClient(); 
        ~UdpClient(); 
    
        bool Connect(); 
        bool Disconnect(); 
        bool Send(); 
        bool Receive(); 
        ... 
    }; 
    

    然而,在我的電腦網絡上的知識仍然是初步的,所以我覺得很難計算機網絡概念轉化成C++的設計。例如,在上面的設計中,我不知道「Port」在哪裏。如果我有「Port」類和「Socket」類,「Port」類是否包含「Socket」類或相反或無意義?

    如果您能就上述設計給我一些反饋,我會很感激。

    • 我已經對Boost.Asio做了一個簡短的介紹,看看它是如何設計的。
    • 對不起,如果我的問題含糊不清。
  • 回答

    2

    典型的插座抽象模型

    • 插座,一些在服務器端
    • 客戶,一些仿照服務器端(一個插座有許多客戶)
    • 連接,模擬客戶端end

    通常,端口號是服務器上的socket.listen方法的一部分,以及cl上的connection.connect方法的一部分ient

    與IP地址相同

    +0

    感謝您的回覆。我想在服務器端和客戶端更像是「套接字」,例如[link](http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/PracticalSocket.h) 。 「連接」也包含一個套接字對象作爲其成員變量?所以,如果你做了像connection.connect(「IP地址」,「端口」),然後在內部創建一個套接字對象並調用WSAConnect()? – jpen

    +0

    從我的角度來看'socket'是用戶(編碼器)在服務器端需要了解的東西。在引擎蓋下還有一個名爲「套接字」的wsa結構,每一端都有一個內部實現細節,您應該隱藏起來 – pm100

    +0

    因此,如何更改上面的層次結構?順便說一句,我的設計只關心客戶端(我沒有任何控制服務器端實現)。我最初的想法是隱藏「TcpClient」和「UdpClient」中的套接字句柄。 – jpen