快捷搜索:  汽车  科技

socket编程中常用函数,TcpSocket编程之Delphi与其他语言的字符串通信

socket编程中常用函数,TcpSocket编程之Delphi与其他语言的字符串通信连接按钮单击事件代码:界面中控件的设置就不再赘述,主要代码为连接按钮单击事件、发送按钮单击事件、接收线程。服务端采用 Python 语言的 Twisted 框架来开发,具体 Twisted 框架的工作原理在此不做赘述,代码如下:# coding: utf-8 from twisted.internet.Protocol import Protocol from twisted.internet.protocol import Factory from twisted.internet.endpoints import TCP4ServerEndpoint from twisted.internet import reactor class Device(Protocol): def connectionMade(self): print('Connecte

关键字:Tcp Scoket、Delphi、Indy、Python、Twisted

对于 Tcp Socket 编程,异种语言之间的通信在日常开发中经常会用到。今天,我们通过 Delphi 和 Python 语言来做一个 Socket 通信的示例。通信数据采用字符串形式来直接传输。

客户端:Delphi、Indy

服务端:Python、Twisted

7.1 服务端编程

服务端采用 Python 语言的 Twisted 框架来开发,具体 Twisted 框架的工作原理在此不做赘述,代码如下:

# coding: utf-8 from twisted.internet.Protocol import Protocol from twisted.internet.protocol import Factory from twisted.internet.endpoints import TCP4ServerEndpoint from twisted.internet import reactor class Device(Protocol): def connectionMade(self): print('Connected from %s:%s.' % (self.transport.getPeer().host self.transport.getPeer().port)) self.transport.write('$Welcome!$'.encode('utf-8')) def connectionLost(self reason): print('Disconnected from %s:%s.' % (self.transport.getPeer().host self.transport.getPeer().port)) print(reason) def dataReceived(self data): print('Recieved from %s:%s.' % ( self.transport.getPeer().host self.transport.getPeer().port)) s = data.decode('utf-8') print(s) self.transport.write('$OK!$'.encode('utf-8')) class DeviceFactory(Factory): def buildProtocol(self addr): print(addr) # addr为创建连接时客户端的地址 return Device() endpoint = TCP4ServerEndpoint(reactor 9123) endpoint.listen(DeviceFactory()) reactor.run()

代码中字符串的开头和结尾的 ”$“ 字符是数据传输的开始和结束标志。

7.2 客户端编程

客户端采用 CodeTyphon 来开发,组件采用 Indy,界面如下:

socket编程中常用函数,TcpSocket编程之Delphi与其他语言的字符串通信(1)

界面中控件的设置就不再赘述,主要代码为连接按钮单击事件、发送按钮单击事件、接收线程。

连接按钮单击事件代码:

procedure TForm1.ConnectButtonClick(Sender: TObject); begin if HostEdit.Text = '' then begin Application.MessageBox('请设置地址!' '提示'); Exit; end; IdTCPClient.Host:=HostEdit.Text; IdTCPClient.Port:=PortSpinEdit.Value; IdTCPClient.Connect; if IdTCPClient.Connected then begin Application.MessageBox('连接成功!' '提示'); ConnectButton.Enabled:=False; DisconnectButton.Enabled:=True; // 启动读取线程 ReadThread:=TReadThread.Create(True); ReadThread.FreeOnTerminate:=True; ReadThread.Start; end else begin Application.MessageBox('连接失败!' '提示'); end; end;

发送按钮单击事件代码:

procedure TForm1.SendButtonClick(Sender: TObject); var s: String; begin if Trim(SendEdit.Text) = '' then begin Application.MessageBox('请输入要发送的内容!' '提示'); Exit; end; s:='$' SendEdit.Text '$'; IdTCPClient.IOHandler.Write(s); RecievedMemo.Lines.Add('发送:' s); SendEdit.Text:=''; end;

在字符串传输时,可以直接使用 IdTCPClient.IOHandler.Write 过程发送字符串数据,字符串的开头和结尾的 ”$“ 字符是数据传输的开始和结束标志。

接收线程代码:

unit unitreadthread; {$mode ObjFPC}{$H } interface uses Classes SysUtils IdGlobal; type TReadThread = class(TTHread) private protected procedure Execute; Override; end; implementation uses unitmain; procedure TReadThread.Execute; var s: String; begin while not Self.Terminated do begin if not Form1.IdTCPClient.Connected then Self.Terminate else try // ReadLn s:=Form1.IdTCPClient.IOHandler.ReadLn; Form1.RecievedMemo.Lines.Add(s); except end; end; end; end.

在 Delphi 中接收服务端传输的字符串可以使用 IdTCPClient.IOHandler.ReadLn 函数,其读取的结果为字符串,也可以使用先读取字节码,然后转换成字符串,代码如下:

procedure TReadThread.Execute; var s: String; bytes: TIdBytes; begin while not Self.Terminated do begin if not Form1.IdTCPClient.Connected then Self.Terminate else try // ReadBytes Form1.IdTCPClient.IOHandler.ReadBytes(bytes -1 False); s:=BytesToString(bytes); Form1.RecievedMemo.Lines.Add('收到:' s.Split('$')[1]); except end; end; end;

ReadBytes 过程的原型:

procedure ReadBytes( var VBuffer: TIdBytes; AByteCount: Integer; AAppend: boolean = true ); virtual;

说明:

ReadBytes是一个虚拟过程,用于执行IOHandler的读取请求。 VBuffer是用于存储从IOHandler连接的数据源读取的值的变量参数。 AByteCount表示读取请求所需的字节值数。当AByteCount包含0(零)时,不会从IOHandler的数据源读取任何数据。当AByteCount包含-1时,将从数据源读取数据,直到断开连接或超过ReadTimeout值。 ReadBytes从IOHandler数据源读取数据,直到InputBuffer中累积了AByteCount中的字节数,或者CheckForDisconnect中断读取请求。 成功完成读取请求后,将值从InputBuffer提取到VBuffer中。 AAppend指示从输入缓冲区提取的值应附加到VBuffer中的现有数据。当AAppend为False时,在从InputBuffer提取数据期间,将丢弃VBuffer中的任何值。

由于我们事先不知道服务端传输的字符串长度,所以读取字节时参数 AByteCount 取值为 -1,同时将参数 AAppend 设置为 false,如果设置为 True,则会在 InputBuffer 中追加数据,这样每次取到的数据就包含前面传输的数据。

7.3 小结:

字符串数据传输:

发送字符串

IdTCPClient.IOHandler.Write

接收字符串

IdTCPClient.IOHandler.ReadLn

IdTCPClient.IOHandler.ReadBytes(bytes -1 False); s:=BytesToString(bytes);



猜您喜欢: