2012-06-25 12 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