如何处理TCPClient中接收到的数据? (德尔福 - 印地)
当我从 TCPClient
向 TCPServer
发送消息时,它将使用服务器中的 OnExecute
事件进行处理。现在我想处理客户端中收到的消息,但 TCPClient 没有任何事件。所以我必须创建一个线程来手动处理它们。我该怎么办?
When i send a message from TCPClient
to a TCPServer
it will be handled using OnExecute
event in the server . Now i want to handle the received messages in the Client but TCPClient
doesn't have any event for this. So i have to make a thread to handle them manually. how can i do it ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
正如其他人在回答您的问题时所说的那样,TCP 不是面向消息的协议,而是一种流协议。我将向您展示如何写入和读取一个非常简单的回显服务器(这是我本周为回答其他问题而做的服务器的稍微修改版本):
服务器 OnExecute 方法如下所示:
此服务器以欢迎词开头消息,然后只读取每个字节的连接字节。服务器回复相同的字节,直到接收到的字节为 65(断开连接命令)65 = 0x41 或 $41。然后服务器以一条再见消息结束。
您可以在客户端中执行此操作:
下一个字节过程可以是您想要提供字节的任何内容。例如,要获取用户的输入,您可以将表单的 KeyPreview 设置为 true,并编写一个 OnKeyPress 事件处理程序和 NextByte 函数,如下所示:
用户在表单中写入的任何内容都将发送到服务器,然后从服务器读取那里并添加到 memo1 中。如果输入焦点已位于 Memo1 中,您将看到每个字符两次,一个来自键盘,另一个来自服务器。
因此,为了编写一个从服务器获取信息的简单客户端,您必须知道对服务器的期望。是字符串吗?多个字符串?整数?大批?二进制文件?编码文件?是否有连接结束的标记?如果您要创建自定义服务器/客户端对,这些内容通常在协议中定义或由您定义。
在事先不知道要从服务器获取什么内容的情况下编写通用 TCP 是可能的,但由于协议中的此级别没有通用消息抽象这一事实而变得复杂。
不要对存在传输消息的事实感到困惑,但是单个服务器响应可以分为多个传输消息,然后在客户端重新组装,您的应用程序不会不控制这个。从应用程序的角度来看,套接字是传入字节的流(流)。您将其解释为消息、命令或来自服务器的任何类型的响应的方式取决于您。这同样适用于服务器端......例如 onExecute 事件是一张白纸,您也没有消息抽象。
也许您将消息抽象与命令抽象混合在一起......在基于命令的协议上,客户端发送包含命令的字符串,服务器回复包含响应的字符串(然后可能是更多数据)。看一下 TIdCmdTCPServer/Client 组件。
编辑
在评论中,OP声明她/他想在线程上完成这项工作,我不确定她/他遇到的问题是什么,但我添加了一个线程示例。服务器与之前所示的相同,只是这个简单服务器的客户端部分:
首先,我正在使用的线程类:
然后,我将这两个方法添加到表单中:
As others said in response to your question, TCP is not a message oriented protocol, but a stream one. I'll show you how to write and read to a very simple echo server (this is a slightly modified version of a server I did this week to answer other question):
The server OnExecute method looks like this:
This server starts with a welcome message, then just reads the connection byte per byte. The server replies the same byte, until the received byte is 65 (the disconnect command) 65 = 0x41 or $41. The server then end with a good bye message.
You can do this in a client:
The next byte procedure can be anything you want to provide a byte. For example, to get input from the user, you can turn the KeyPreview of your form to true and write a OnKeyPress event handler and the NextByte function like this:
Anything the user writes in the form will be sent to the server and then read from there and added to memo1. If the input focus is already in Memo1 you'll see each character twice, one from the keyboard and the other form the server.
So, in order to write a simple client that gets info from a server, you have to know what to expect from the server. Is it a string? multiple strings? Integer? array? a binary file? encoded file? Is there a mark for the end of the connection? This things are usually defined at the protocol or by you, if you're creating a custom server/client pair.
To write a generic TCP without prior known of what to get from the server is possible, but complex due to the fact that there's no generic message abstraction at this level in the protocol.
Don't get confused by the fact there's transport messages, but a single server response can be split into several transport messages, and then re-assembled client side, your application don't control this. From an application point of view, the socket is a flow (stream) of incoming bytes. The way you interpret this as a message, a command or any kind of response from the server is up to you. The same is applicable server side... for example the onExecute event is a white sheet where you don't have a message abstraction too.
Maybe you're mixing the messages abstraction with the command abstraction... on a command based protocol the client sends strings containing commands and the server replies with strings containing responses (then probably more data). Take a look at the TIdCmdTCPServer/Client components.
EDIT
In comments OP states s/he wants to make this work on a thread, I'm not sure about what's the problem s/he is having with this, but I'm adding a thread example. The server is the same as shown before, just the client part for this simple server:
First, the thread class I'm using:
Then, I'm adding this two methods to the form:
TCP 不使用消息进行操作。那是基于流的接口。因此,不要期望您会在接收器上收到“消息”。相反,您从套接字读取传入的数据流并根据高级协议对其进行解析。
TCP doesn't operate with messages. That is stream-based interface. Consequently don't expect that you will get a "message" on the receiver. Instead you read incoming data stream from the socket and parse it according to your high-level protocol.
这是我用 Delphi 7 读取/写入的代码。使用 Tcp 事件读取。
Here is my code to Read / Write with Delphi 7. Using the Tcp Event Read.
如果您需要 Indy 客户端处理传入的“消息”(“消息”的定义取决于所使用的协议),我建议您查看协议\IdTelnet 单元中 TIdTelnet 的实现。
该组件使用基于 TIdThread 的接收线程,该线程从 Telnet 服务器异步接收消息,并将它们传递给消息处理程序例程。如果您有类似的协议,这可能是一个很好的起点。
更新:更具体地说,IdTelnet.pas 中的过程 TIdTelnetReadThread.Run; 是异步客户端“魔法”发生的地方,您可以看到它使用 Synchronize 在主线程中运行数据处理- 但是当然您的应用程序也可以在接收线程中进行数据处理,或者将其传递给工作线程以保持主线程不变。该过程不使用循环,因为循环/暂停/重新启动是在 IdThread 中实现的。
If you need the Indy client to handle incoming "messages" (definition of "message" depends on the protocol used), I recommend to take a look at the implementation of TIdTelnet in the protocols\IdTelnet unit.
This component uses a receiving thread, based on a TIdThread, which asynchronously receives messages from the Telnet server, and passes them to a message handler routine. If you have a similar protocol, this could be a good starting point.
Update: to be more specific, the
procedure TIdTelnetReadThread.Run;
in IdTelnet.pas is where the asynchronous client 'magic' happens, as you can see it uses Synchronize to run the data processing in the main thread - but of course your app could also do the data handling in the receiving thread, or pass it to a worker thread to keep the main thread untouched. The procedure does not use a loop, because looping / pausing / restarting is implemented in IdThread.添加一个
TTimer
。将其
Interval
设置为1
。在
OnTimer
事件中写入:不要将
Timer.Interval
设置为其他1
。因为,接收到的数据会在几毫秒后删除。
Add a
TTimer
.Set its
Interval
to1
.Write in
OnTimer
Event:Don't set
Timer.Interval
something else1
.Because, the received data deletes after some milliseconds.