一、 虚拟串口的建立与应用
在WINDOWS平台上,可使用开源的COM0COM建立虚拟串口对,建好的串口对实质上是两个串口的RX与TX互接,向其中的一个端口发送数据,则可以在另一个端口上接收。比如建了COM3和COM4一对虚拟串口,在windows平台的设备管理列表上看到的是下面的样子,使用起来和真实串口几乎无异,用它进行不同应用程序间的数据收发是比较方便的。
1 用VB6的MSCOMM发送数据

程序运行时每秒向串口3发送数据

完整程序代码
vbnet
Option Explicit
Private Sub Command1_Click()
On Error Resume Next
Dim iComNo As Integer
iComNo = Val(Text1.Text)
If MSComm1.PortOpen = False Then
MSComm1.CommPort = iComNo
MSComm1.Settings = "9600,N,8,1"
MSComm1.PortOpen = True
End If
MSComm1.Output = Time$ + " --- " + Text2.Text
End Sub
Private Sub Form_Close()
On Error Resume Next
If MSComm1.PortOpen = True Then
MSComm1.PortOpen = False
End If
End Sub
Private Sub Timer1_Timer()
On Error Resume Next
Command1_Click
End Sub
2 用Delphi7安装MSCOMM接收数据

Delphi7完整代码
Delphi
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, OleCtrls, MSCommLib_TLB;
type
TForm1 = class(TForm)
MSComm1: TMSComm;
Edit1: TEdit;
Label1: TLabel;
Button1: TButton;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure MSComm1Comm(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
ComNo, ErrCode: integer;
handle: hwnd;
begin
val(Edit1.Text, ComNo, ErrCode);
try
MSComm1.CommPort := ComNo;
MSComm1.RThreshold := 1;
MSComm1.PortOpen := True;
except
end;
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if MSComm1.PortOpen = True then
MSComm1.PortOpen := False;
end;
procedure TForm1.MSComm1Comm(Sender: TObject);
var
sMyString: string;
begin
if MSComm1.CommEvent = 2 then
Listbox1.Items.Insert (0, MSComm1.Input);
if Listbox1.Items.Count >= 100 then
ListBox1.Items.Delete(100);
end;
end.
3 用Delphi7安装SPComm接收数据

Delphi7完整代码
Delphi
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, SPComm;
type
TForm1 = class(TForm)
Comm1: TComm;
Edit1: TEdit;
Label1: TLabel;
ListBox1: TListBox;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
ComNo: integer;
ErrCode: integer;
begin
Val(Edit1.Text, ComNo, ErrCode);
Comm1.CommName := 'COM' + Trim(IntToStr(ComNo));
try
Comm1.StartComm;
except
end;
end;
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
begin
ListBox1.Items.Insert(0, PAnsiChar(Buffer));
if ListBox1.Items.Count >=100 then
ListBox1.Items.Delete(100);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
try
Comm1.StopComm;
except
end;
end;
end.
4 用Lazarus安装SPComm接收数据

程序代码和Delphi7安装SPComm完全一样。
二、 基于UDP的数据传送
以VB6和勇芳VisualFreeBasic编程为例。
1 用VB6加winsock发送udp数据
VB6加上部件Winsock如下图,再放一个Timer,定时间隔1000毫秒,按Command1按钮。

Winsock属性设置

完整VB6程序代码
vbnet
Option Explicit
Private Sub Command1_Click()
Winsock1.SendData (Time$)
End Sub
Private Sub Timer1_Timer()
Command1_Click
End Sub
2 用勇芳VisualFreeBasic的udp接收数据

窗体上放上Network控件,Text2,和Command2。Text1和Command1留在上面没用。
Network1属性设置如下图。

完整程序代码(标注全部是勇芳VisualFreeBasic默认的)
vbnet
'这是标准的工程模版,你也可做自己的模版。
'写好工程,复制全部文件到VFB软件文件夹里【template】里即可,子文件夹名为 VFB新建工程里显示的名称
'快去打造属于你自己的工程模版吧。
Dim Shared hwndnetwk1 As hwnd
Sub Form1_Command1_BN_Clicked(hWndForm As hWnd, hWndControl As hWnd)
'Network1.UdpPostData("127.0.0.1",2000,"abcd")
End Sub
Sub Form1_Command2_BN_Clicked(hWndForm As hWnd, hWndControl As hWnd)
End Sub
'[Form1]事件 : 即将关闭窗口,返回非0可阻止关闭
'hWndForm 当前窗口的句柄(WIN系统用来识别窗口的一个编号,如果多开本窗口,必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
Function Form1_WM_Close(hWndForm As hWnd) As LResult
'hwndnetwk1 = Network1.UdpClose
Function = FALSE ' 返回 TRUE 阻止关闭窗口。
End Function
'[Form1]事件 : 完成创建窗口及所有的控件后,此时窗口还未显示。注:自定义消息里 WM_Create 此时还未创建控件和初始赋值。
'hWndForm 当前窗口的句柄(WIN系统用来识别窗口的一个编号,如果多开本窗口,必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
'UserData 来自显示窗口最后1个参数,例: Form2.Show(父窗口句柄,模式,UserData)
Sub Form1_WM_Create(hWndForm As hWnd,UserData As Integer)
'hwndnetwk1 = Network1.UdpOpen
End Sub
'[Form1.Network2]事件 : UDP接收到新数据
'hWndForm 当前窗口的句柄(WIN系统用来识别窗口的一个编号,如果多开本窗口,必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
'UDP通信,只管发送数据给对方,不管对方有没收到,可能会发生丢包的事情,优点是速度快。
' ***** 要想接收数据,必须启用UDP通信服务 *****
'nn.ip As String '对方的IP地址
'nn.Port As UShort '对方的端口
'nn.Dat As String '收到的数据(是数据不一定是文本),最多4096字节
Sub Form1_Network2_UdpNewData(hWndForm As hWnd, nn As Network_Data)
Print "接收数据,内容:" , nn.Dat '非文本数据不要打印
'假如是数据可以用 For i=0 To Len(nn.Dat)-1 :nn.Dat[i] :Next 读取每个字节
'还可以用 Network1.UdpPostData(nn.ip,nn.Port,"数据") 发给对方数据
Text1.text = nn.Dat
End Sub
'[Form1.Network1]事件 : UDP接收到新数据
'hWndForm 当前窗口的句柄(WIN系统用来识别窗口的一个编号,如果多开本窗口,必须 Me.hWndForm = hWndForm 后才可以执行后续操作本窗口的代码)
'UDP通信,只管发送数据给对方,不管对方有没收到,可能会发生丢包的事情,优点是速度快。
' ***** 要想接收数据,必须启用UDP通信服务 *****
'nn.ip As String '对方的IP地址
'nn.Port As UShort '对方的端口
'nn.Dat As String '收到的数据(是数据不一定是文本),最多4096字节
Sub Form1_Network1_UdpNewData(hWndForm As hWnd, nn As Network_Data)
Print "接收数据,内容:" , nn.Dat '非文本数据不要打印
'假如是数据可以用 For i=0 To Len(nn.Dat)-1 :nn.Dat[i] :Next 读取每个字节
'还可以用 Network1.UdpPostData(nn.ip,nn.Port,"数据") 发给对方数据
Text2.text = nn.Dat
End Sub
程序使用的2000端口在本机防火墙上打开,WIN11下程序运行时自动会提示是否要打开,点确认即自动打开。两个程序运行后,VB6自动向VisualFreeBasic发送数据,不用握手,直接往UDP端口送数据。在本机上和本地网络上使用是一样的。
实践习练程序放在CSDN链接里了