【问题标题】:QT QTcpServer telnet taking characters \r\nQT QTcpServer telnet 获取字符 \r\n
【发布时间】:2011-07-29 03:44:09
【问题描述】:

我正在写QTcpServer。我使用telnet.exe 作为客户端进行测试。在新的客户端连接上,我的服务器会向显示的客户端发送 Hi! 消息 - 到目前为止一切都很好。

但是当我在telnet.exe 窗口中输入内容时,每个字符都会发出一个readyRead()。我只希望它在\r\n 之后发送!有什么问题?这是Windows中telnet.exe的本质吗?因为我在我的 linux 机器上使用了telnet,它只在\r\n 之后发送字符串,正如预期的那样。

【问题讨论】:

    标签: windows qt4 telnet qtnetwork qtcpserver


    【解决方案1】:

    不幸的是,Windows telnet.exe 客户端就是这样工作的,无法更改。

    在处理 TCP 流时,您不能依赖这样的客户端特定行为。 TCP 确实保证消息边界,但它确实保证,从您的角度来看,数据按照客户端写入的相同顺序传递。在设计协议时必须考虑到这一点。

    您需要缓冲传入数据并在应用程序协议级别进行处理。常见的解决方案包括定义消息终止序列(以及如果该序列可以出现在正常消息中,则转义该序列的机制) - 例如,\r\n 可能是这种情况下的终止序列 - 或者您可以打包发送的数据前缀它带有后续消息长度,或者您可以使用专用的消息库(例如ZeroMQActiveMQ - 但不幸的是您不能使用Qt的网络)等。

    【讨论】:

      【解决方案2】:

      不要键入您的消息,而是按 CTRL + ],然后键入 send YOURMESSAGE\r\n

      【讨论】:

        【解决方案3】:

        是的,带有 CR LF 的 windows 和 linux 之间存在一些差异,这是“正常的”。

        一种很好的方法是利用缓冲区,然后等待数据准备好或超时。例如,您的分隔符标记可以是“\r”,如果您在删除它后得到一个“\n”。

        这是一个期望来自自定义协议的令牌的示例:

        int Connection::readDataIntoBuffer(int maxSize)
         {
             if (maxSize > MaxBufferSize)
                 return 0;
        
             int numBytesBeforeRead = buffer.size();
             if (numBytesBeforeRead == MaxBufferSize) {
                 abort();
                 return 0;
             }
        
             while (bytesAvailable() > 0 && buffer.size() < maxSize) {
                 buffer.append(read(1));
                 if (buffer.endsWith(SeparatorToken))
                     break;
             }
             return buffer.size() - numBytesBeforeRead;
         }
        

        http://doc.qt.nokia.com/stable/network-network-chat-connection-cpp.html

        根据您的需要,另一个建议是尝试坚持一些标准协议。像这样,您可以使用不同类型的客户端进行测试。

        如果您想坚持您的自定义协议,我建议您编写自己的客户端并编写适当的测试用例以与您的服务器协作。 Qt 让它变得简单快捷;) 看看网络示例。

        编辑:

        您可以考虑在您的QTcpSocket 上使用readline() 而不是read(),后者是QIODevice。它等待换行符而不是 read() (请参阅下面的文档摘录)。但是,这对何时结束行的控制较少:

        qint64 QIODevice::readLine ( char * data, qint64 maxSize )
        

        来自文档:

        数据被读取,直到任何一个 满足以下条件:

        • 读取第一个“\n”字符。
        • maxSize - 读取 1 个字节。
        • 检测到设备数据的结尾。

        Qt 的秘诀是异步信号驱动设计。有关一些想法,请参阅文章Threads, Events and QObjects 中的网络/状态机部分。

        【讨论】:

        • 这里需要使用RFB协议。但是 libvnc 是 GPL。所以我认为与从头开始编写 RFB 协议相比,创建一个本土协议更好。
        • @Neel:我已经编辑了可能更具体针对您的问题的部分回复。如果你有一个相对简单的需求,你自己的协议可以工作。但是,既然您正在研究 RFB,那么实现它并不是一件小事!
        • +1 为您提供帮助。在现实世界的场景中,我将使用我自己的客户端程序。那么即使那样,我发送的字节是否也能保证是原子的?例如如果我的客户发送hallo 是否保证它会去hallo 或者它甚至可能去h a llo 即使我使用我自己的客户端程序来处理 Socket 的内部性质?目前我正在使用Hercules TCP 客户端程序而不是 telnet 进行测试,它会根据需要发送它。不是性格明智。
        • @NeelBasu 一个相当老的话题,但值得注意的是,您不知道您是否会收到halloha llo 或任何其他拆分组合。这是一个传输细节。你可以确定的是,如果你收到ha,然后阻塞直到你收到llo,这是消息的其余部分,那么ha++llo将是hallo .所以消息的接收与消息描述不同——这就是为什么它们被称为streams
        猜你喜欢
        • 2013-12-04
        • 2017-01-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多