【问题标题】:Qt - Create WriteOnly and ReadOnly socketQt - 创建 WriteOnly 和 ReadOnly 套接字
【发布时间】:2017-09-10 13:50:35
【问题描述】:

我有一个套接字描述符。

我需要两个插座。其中一个仅用于 ReadOnly,另一个用于 WriteOnly。

不可能吗?如果有,怎么做?

【问题讨论】:

    标签: qt sockets readonly writeonly


    【解决方案1】:

    Qt 的套接字不支持每个本地套接字拥有多个套接字对象,但您可以通过创建适当的单向接口来近似这一点。

    在下面的示例中,接口不执行任何缓冲,因此它们强制每个套接字的每种接口只有一次。一旦你使用了接口,你不应该直接使用套接字。

    // https://github.com/KubaO/stackoverflown/tree/master/questions/socket-split-43409221
    #include <QtNetwork>
    
    class SocketBase : public QIODevice {
       Q_OBJECT
    public:
       explicit SocketBase(QAbstractSocket * parent) : QIODevice{parent} {
          connect(parent, &QAbstractSocket::connected, this, &SocketBase::connected);
          connect(parent, &QAbstractSocket::disconnected, this, &SocketBase::disconnected);
          connect(parent, &QAbstractSocket::stateChanged, this, [this](QAbstractSocket::SocketState state){
             emit stateChanged(state);
             setOpenMode(m_dev->openMode());
          });
          connect(parent,
                  static_cast<void(QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
                  this, [this](QAbstractSocket::SocketError error){
             setErrorString(m_dev->errorString());
             emit this->error(error);
          });
          setOpenMode(m_dev->openMode());
       }
       QAbstractSocket::SocketError error() const {
          return m_dev->error();
       }
       QAbstractSocket::SocketState state() const {
          return m_dev->state();
       }
       Q_SIGNAL void connected();
       Q_SIGNAL void disconnected();
       Q_SIGNAL void error(QAbstractSocket::SocketError);
       Q_SIGNAL void stateChanged(QAbstractSocket::SocketState);
       bool isSequential() const override { return true; }
    protected:
       QAbstractSocket * const m_dev = static_cast<QAbstractSocket*>(parent());
    };
    
    class ReadSocket : public SocketBase {
       Q_OBJECT
    public:
       explicit ReadSocket(QAbstractSocket * parent) : SocketBase(parent) {
          for (auto proxy : parent->findChildren<ReadSocket*>())
             Q_ASSERT(proxy == this);
          connect(m_dev, &QIODevice::readyRead, this, &QIODevice::readyRead);
       }
       bool atEnd() const override {
          return QIODevice::atEnd() && m_dev->atEnd();
       }
       qint64 bytesAvailable() const override {
          return m_dev->bytesAvailable();
       }
       bool canReadLine() const override {
          return m_dev->canReadLine();
       }
    protected:
       qint64 readData(char * data, qint64 maxLength) override {
          return m_dev->read(data, maxLength);
       }
       qint64 readLineData(char *data, qint64 maxLength) override {
          return m_dev->readLine(data, maxLength);
       }
       qint64 writeData(const char *, qint64) override {
          return -1;
       }
    };
    
    class WriteSocket : public SocketBase {
       Q_OBJECT
    public:
       explicit WriteSocket(QAbstractSocket * parent) : SocketBase(parent) {
          for (auto proxy : parent->findChildren<WriteSocket*>())
             Q_ASSERT(proxy == this);
          connect(m_dev, &QIODevice::bytesWritten, this, &QIODevice::bytesWritten);
       }
       qint64 bytesToWrite() const override {
          return m_dev->bytesToWrite();
       }
       bool flush() {
          return m_dev->flush();
       }
    protected:
       qint64 readData(char *, qint64) override {
          return -1;
       }
       qint64 writeData(const char * data, qint64 length) override {
          return m_dev->write(data, length);
       }
    };
    
    int main(int argc, char *argv[])
    {
       QCoreApplication app{argc, argv};
       QHostAddress addr{"127.0.0.1"};
       quint16 port{9341};
    
       QTcpServer server;
       if (! server.listen(addr, port)) qFatal("can't listen");
       QObject::connect(&server, &QTcpServer::newConnection, &server, [&]{
          auto s = server.nextPendingConnection();
          QObject::connect(s, &QTcpSocket::readyRead, s, [s]{
             s->write(s->readAll());
          });
          QObject::connect(s, &QTcpSocket::disconnected, s, &QObject::deleteLater);
       });
    
       const char data_[] = "dhfalksjdfhaklsdhfklasdfs";
       auto const data = QByteArray::fromRawData(data_, sizeof(data_));
       QTcpSocket client;
       WriteSocket writer(&client);
       ReadSocket reader(&client);
       QObject::connect(&writer, &WriteSocket::connected, [&]{
          writer.write(data);
       });
       QObject::connect(&reader, &ReadSocket::readyRead, [&]{
          if (reader.bytesAvailable() >= data.size()) {
             auto const read = reader.read(data.size());
             Q_ASSERT(read == data);
             qApp->quit();
          }
       });
       client.connectToHost(addr, port);
       return app.exec();
    }
    #include "main.moc"
    

    【讨论】:

      猜你喜欢
      • 2013-03-04
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 1970-01-01
      • 2012-11-08
      相关资源
      最近更新 更多