C ++中面向对象的客户端套接字应用程序设计

时间:2012-06-25 21:30:10

标签: c++ oop winsock2

几个星期前我开始使用Windows套接字编程。

到目前为止,我已经创建了一个C风格客户端应用程序(基于IOCP),它与VC ++ 2010中的网络硬件设备进行通信。应用程序通过LAN或串行端口与设备(充当服务器)异步通信:

  • 创建套接字/或串口的句柄
  • 连接到服务器
  • 构建std :: vector类型的命令(例如,登录命令)
  • 通过套接字或串口发送命令
  • 通过套接字或串口接收响应
  • 断开与服务器的连接

现在我想使我现有的客户端应用程序更加面向对象,并且我已经提出了以下类层次结构(省略了参数):

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 ++设计很困难。例如,在上面的设计中,我不知道“端口”的位置。如果我有“端口”类和“套接字”类,“端口”类是否包含“套接字”类或相反或无意义?< / p>

如果你能给我一些关于上述设计的反馈,我将不胜感激。

  • 我已经非常简短地看了一下Boost.Asio,看看它是如何设计的。
  • 如果我的问题含糊不清,我很抱歉。

1 个答案:

答案 0 :(得分:2)

典型的套接字抽象模型

  • socket,服务器端的东西
  • 客户端,在服务器端建模的东西(一个套接字有很多客户端)
  • 连接,以客户端为蓝本建模

通常,端口号是服务器上的socket.listen方法的一部分,是客户端上connection.connect方法的一部分

与IP地址相同