QT QTcpServer telnet的字符\r\n。

时间:2021-07-21 15:18:10

I'm writing a QTcpServer. I used telnet.exe as a client for testing. Upon a new client connection my server sends a Hi! message to the client which is displayed - all is well and fine so far.

我正在写一个QTcpServer。我使用telnet。作为测试的客户。在一个新的客户机连接上,我的服务器发送一个Hi!向客户端显示的消息——到目前为止一切正常。

But when I type something in the telnet.exe window, a readyRead() is emitted for each character. I only want it to be sent after \r\n! What's the problem? Is it the nature of telnet.exe in Windows? Cause I've used telnet on my linux box and it only sends the string after \r\n, as expected.

但当我在telnet中输入内容时。exe窗口,为每个字符发送一个readyRead()。我只是想让它在收到后发送!是什么问题?是telnet的本质。exe在Windows ?因为我在我的linux框上使用了telnet,它只会像预期的那样,在\r\n之后发送字符串。

3 个解决方案

#1


3  

Unfortunately, that's how the Windows telnet.exe client works and there's no way to change that.

不幸的是,这就是Windows的telnet。exe客户端工作,没有办法改变。

You must not rely on client-specific behavior like this when handling TCP streams. TCP does not guarantee message boundaries, but it does guarantee that, from your point of view, the data is delivered int he same order it was written by the client. You must take this into account when designing your protocol.

在处理TCP流时,不能像这样依赖于客户端的行为。TCP不保证消息边界,但它确实保证了,从您的角度来看,数据是由客户端所写的相同的顺序交付的。在设计协议时,必须考虑到这一点。

You'll need to buffer incoming data and handle this at the application protocol level. Common solutions include defining a message terminator sequence (and a mechanism for escaping that sequence if it can appear inside the normal messages) - for example, \r\n could be the terminator sequence in this scenario -, or you can packetize sent data prefixing it with the follow-up message length, or you can use dedicated messaging libraries (such as ZeroMQ or ActiveMQ - but then you can't use Qt's networking, unfortunately), etc.

您需要缓冲传入的数据并在应用程序协议级别处理它。常见的解决方案包括定义一个消息终结者序列(序列和转义机制,如果它能出现在正常的消息)——例如,\ r \ n可以终结者序列在这个场景中,或者你可以分成包发送数据前缀的后续消息长度,或者你可以使用专用的消息传递库(如ZeroMQ或ActiveMQ -但你不能使用Qt的网络,不幸的是),等等。

#2


3  

Instead of typing your message, press CTRL + ], and then type send YOURMESSAGE\r\n

而不是输入你的信息,按CTRL +],然后输入发送你的消息\r\n。

#3


1  

Yes, there are some differences between windows and linux with CR LF, it's "normal".

是的,在windows和linux之间有一些区别,它是“正常的”。

One approach that works nice is to make use of buffer and then wait for your data to be ready or timeout. For exmaple your seperator token can be “\r” and if you get an “\n” after just drop it.

一个行之有效的方法是利用缓冲区,然后等待数据准备就绪或超时。对于exmaple,您的seperator令牌可以是“\r”,如果您在删除它之后得到一个“\n”。

Here is an example expecting a token from a custom protocol:

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

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;
 }

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

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

Depending on what you need another suggestion is to try an stick to some standard protocol. Like this you can test with different type of clients.

根据你的需要,另一个建议是尝试使用某种标准的协议。像这样,您可以测试不同类型的客户机。

If you want to stick to your custom protocol I suggest you write your own client and write proper test cases to collaborate with your server. Qt makes it easy and fast ;) Take a look at the network examples.

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

Edit:

编辑:

You might consider readline() instead of read() on your QTcpSocket which is an QIODevice. It waits for a newline instead of read() (see the doc excerpt below). However this gives less control over when to end your line:

您可以考虑readline()而不是在QTcpSocket上读取(),这是一个QIODevice。它等待一个换行而不是read()(参见下面的doc摘录)。然而,这给你在何时结束你的底线提供了更少的控制:

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

From the doc:

从医生:

Data is read until either of the following conditions are met:

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

  • The first '\n' character is read.
  • 第一个“\n”字符被读取。
  • maxSize - 1 bytes are read.
  • maxSize - 1字节被读取。
  • The end of the device data is detected.
  • 检测到设备数据的结束。

The secret ingredient in Qt is asynchronous signal driven-design. See the section Networking / State Machines section in the article Threads, Events and QObjects for some ideas.

Qt的秘密成分是异步信号驱动设计。在文章的线程、事件和QObjects中,可以看到一些概念的节联网/状态机部分。

#1


3  

Unfortunately, that's how the Windows telnet.exe client works and there's no way to change that.

不幸的是,这就是Windows的telnet。exe客户端工作,没有办法改变。

You must not rely on client-specific behavior like this when handling TCP streams. TCP does not guarantee message boundaries, but it does guarantee that, from your point of view, the data is delivered int he same order it was written by the client. You must take this into account when designing your protocol.

在处理TCP流时,不能像这样依赖于客户端的行为。TCP不保证消息边界,但它确实保证了,从您的角度来看,数据是由客户端所写的相同的顺序交付的。在设计协议时,必须考虑到这一点。

You'll need to buffer incoming data and handle this at the application protocol level. Common solutions include defining a message terminator sequence (and a mechanism for escaping that sequence if it can appear inside the normal messages) - for example, \r\n could be the terminator sequence in this scenario -, or you can packetize sent data prefixing it with the follow-up message length, or you can use dedicated messaging libraries (such as ZeroMQ or ActiveMQ - but then you can't use Qt's networking, unfortunately), etc.

您需要缓冲传入的数据并在应用程序协议级别处理它。常见的解决方案包括定义一个消息终结者序列(序列和转义机制,如果它能出现在正常的消息)——例如,\ r \ n可以终结者序列在这个场景中,或者你可以分成包发送数据前缀的后续消息长度,或者你可以使用专用的消息传递库(如ZeroMQ或ActiveMQ -但你不能使用Qt的网络,不幸的是),等等。

#2


3  

Instead of typing your message, press CTRL + ], and then type send YOURMESSAGE\r\n

而不是输入你的信息,按CTRL +],然后输入发送你的消息\r\n。

#3


1  

Yes, there are some differences between windows and linux with CR LF, it's "normal".

是的,在windows和linux之间有一些区别,它是“正常的”。

One approach that works nice is to make use of buffer and then wait for your data to be ready or timeout. For exmaple your seperator token can be “\r” and if you get an “\n” after just drop it.

一个行之有效的方法是利用缓冲区,然后等待数据准备就绪或超时。对于exmaple,您的seperator令牌可以是“\r”,如果您在删除它之后得到一个“\n”。

Here is an example expecting a token from a custom protocol:

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

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;
 }

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

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

Depending on what you need another suggestion is to try an stick to some standard protocol. Like this you can test with different type of clients.

根据你的需要,另一个建议是尝试使用某种标准的协议。像这样,您可以测试不同类型的客户机。

If you want to stick to your custom protocol I suggest you write your own client and write proper test cases to collaborate with your server. Qt makes it easy and fast ;) Take a look at the network examples.

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

Edit:

编辑:

You might consider readline() instead of read() on your QTcpSocket which is an QIODevice. It waits for a newline instead of read() (see the doc excerpt below). However this gives less control over when to end your line:

您可以考虑readline()而不是在QTcpSocket上读取(),这是一个QIODevice。它等待一个换行而不是read()(参见下面的doc摘录)。然而,这给你在何时结束你的底线提供了更少的控制:

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

From the doc:

从医生:

Data is read until either of the following conditions are met:

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

  • The first '\n' character is read.
  • 第一个“\n”字符被读取。
  • maxSize - 1 bytes are read.
  • maxSize - 1字节被读取。
  • The end of the device data is detected.
  • 检测到设备数据的结束。

The secret ingredient in Qt is asynchronous signal driven-design. See the section Networking / State Machines section in the article Threads, Events and QObjects for some ideas.

Qt的秘密成分是异步信号驱动设计。在文章的线程、事件和QObjects中,可以看到一些概念的节联网/状态机部分。