开发通信软件的技术与技巧
国防大学图书馆技术室 王渤
【提要】随着计算机应用领域的不断扩展,计算机之间的远程通信用得也越来越广泛,计算机间的远程通信所使用的通信软件,在市面上可以买到,但是通用的通信软件虽然能发送和接收文件,在许方情况下这些通信软件并不能满足实际工作的需要。本文就这一技术进行了探讨,介绍了有关的知识和技术,并由实例分步骤说明如何进行通信软件的开发。
一、前言
本文将以vb5.0所带的通信控件mscomm进行通信软件的开发,它有约30个属性和事件(可以从联机帮助中找到其使用资料)。本文简述它的主要属性及事件,并归类整理。
利用串行端口与调制解调器进行连接时,对于用mscomm控件编制通信软件来说,只需了解以下五根线的代号及作用。以下五根线的高电平/低电平状态分别对应mscomm控件的相应属性的true/false值。
(1)dtr线:pc发往modem,表示pc机是否已准备好。
(2)rts线:pc发往modem,表示pc机是否允许modem发回数据.
(3)dsr线:modem发往pc,表示modem是否已做好操作准备
(4)cts线:modem发往pc,表示modem是否允许发送数据
(5)cd线:modem发往pc,表示moedm已经与呼叫的远方modem处于连结状态
二、mscomm控件的属性
属性
值
作用
commport
用1,2,...表示串口com1,com2....
设置或返回联接modem的串口的编号
settings
例用"19200,n,8,1"表示传输速率为19200bps,没有奇偶校验位,8位数据位,1位停止位。
设置或返回通信参数。
handshaking
0没有握手协议,不考虑流量控制。
1xon/xoff,即在数据流中嵌如控制苻来进行流控。
2rts/cts,既由信号线rts/cts自动进行流量控制(常用)。
3两者皆可。
设置或返回硬件握手协议,指的是pc机modem之间为了控制流速而约定的内部协议。
portopen
true/false可以打开/关闭端口。
打开或关闭端口。
outbuffersize
传输缓冲区的字节数,如选1024。
设置或返回传输缓冲区大小。
output
variant型变量。
向传输缓冲区写数据流。
传输文本数据时,应将string型数据放入variant变量,传输二进制数据(即按字节)时,应将byte型数组数据放入variant变量
inbuffersize
接收缓冲区的字节数,如选1024。
设置或返回接收缓冲区大小。
inputmode
0用input属性接收文本型数据。
1用input属性接收二进制数据。
设置或返回接收数据的数据类型。
inbuffercount
integer型
返回接收缓冲区中已传到但还未取走的字符个数。
input
当inputmode属性值为0(文本模式)时,变量中含string型数据。
当inputmode属性值为1(二进制模式)时,变量中含byte型数组数据。
将接收缓冲区中收到的数据读入变量。
dtrenabled
rtsenabled
dsrholding
ctsholding
cdholding
均取值true/false
用于读取或控制pc机与modem之间的交互状态。需运用好。例如,应在读取到dsrholding属性值为true时再向modem发出命令。应当在载波检测到以后(cdholding属性为true)时再向modem发送数据。
三、mscomm控件的触发事件
mscomm控件只使用一个事件oncomm,用属性commevent的十七个值来区分不同的触发时机。主要有以下几个:
(1)commevent=1时:传输缓冲区中的字符个数已少于sthreshold(可设置的属性值)个。
(2)commevent=2时:接收缓冲区中收到hreshold(可设置的属性值)个个字符,利用此事件可编写接收数据的过程。
(3)commevent=3时:cts线发生变化。
(4)commevent=4时:dsr线发生变化。
(5)commevent=5时:cd线发生变化。
(6)commevent=6时:检测到振铃信号。
另外十种情况是通信错误时产生,即错误代码。
四、通信软件程序实现
1、首先是通信参数设置,主要就是可以设置端口号,波特率,数据位,停止位,奇偶校验位及设置硬件握手协议,这些设置较为简单。
2、向modem发出dtr(已准备好)信号,如下例程:
if mscomm1.portopen then
mscomm1.dtrenable=true
else
mscomm1.dtrenable=false
endif
3、打开时向modem发出一些命令来设置参数,其中s0=n(n>=1)自动应答.n为响铃次数;e0/e1关闭/打开命令字符回应;q0/q1modem返回/不返回结果码;m0/m1关闭/打开modem扬声器,例程如下:
if mscomm1.portopen then
do while not mscomm1.ctsholding : loop
outstring="ats0=1e1q0m0"+chr(13)
mscomm1.output=outstring
end if
4、进行拨号设计,需向modem发出atdt命令,如下语句:
mscomm1.output="atdt"+trim(“电话号码”)+chr(13)
5、拨号以后发送数据文件,程序要循环等待并随时判定是否接通。如果modem向pc的回应字符串中含有"connect"或cdholding属性值变为true(检测出载波),则表示已与远方modem连机了,此时可以传输数据。
程序设计发送及接收程序时,需要以下定义:
s_filename = "name" + chr(5) + chr(13) + chr(10)
s_filelen = "lenth" + chr(5) + chr(13) + chr(10)
s_filesend = "begin" + chr(5) + chr(13) + chr(10)
Sub openfiletosend() '打开一个欲发送的文件
hsend = freefile
open sendfn for binary as hsend 'sendfn中含有由用户选定的要传送的文件名。
lf&=lof(hsend) '文件长度为lf&
'开始发送文件名,文件长度,文件开始等信息字符串。
dim data as vrait
data = s_filename
mscomm1.output=data '发出"filename"文件名字串的提示信息
data = sendfn +chr(13)+chr(10)
mscomm1.output=data '发出文件名
data = s_filelen
mscomm1.output=data '发出"filelen"提示字串
data = trim(str(lf&))+chr(13)+chr(10)
mscomm1.output=data '发出文件大小
data = s_filestar
mscomm1.output=data '发出"filestart"提示信息,表示下面文件开始。
dim sendarr() as byte '定义字节型数组
sum=0 '记录累计发送的字节数
bsize=mscomm1.outbuffersize '每次发送的块大小
redim sendarr(1 to bsize) '重新定义读取缓冲
do while sum<lf& '循环发送
if lf&-loc(hsend)<bsize then
bsize=lf&-loc(hsend)
redim sendarr(1 to bsize)
end if
get hsend ,, sendarr '从文件取字节放入字节数组
sendvar=sendarr '转放到variant型变量
'当cts线及cd线为高电平时才可发送,否则需等待。
t=timer+60
l:
if mscomm1.ctsholding and mscomm1.cdholding then
mscomm1.output=sendvar '发送
sum = sum + bsize'累加计数
else
if timer < t then
go to l '循环等待
else
go to closefile '等待时间超过60秒则退出
end if
end if
'等待系统处理完
do
ret = doevents()
loop until mscomm1.outbuffercount = 0
loop '循环发送完毕。
6、接收modem送回的信息和数据文件,该过程是编写mscomm1控件的oncomm事件的处理程序来完成。为了接收文本类型的握手信号,通常使inputmode属性为文本模式。当发现接收到的字符串中有"filestar"+chr(5)+chr(13)+chr(10),则将inputmode属性改为二进制模式。当文件内容接收完(由接收的字节数判断)再将inputmode属性改为文本模式。例程如下:
private static sub mscomm1_oncomm()
select case mscomm1.commevent
case comevreceive '接收缓冲区收到rthreshold个字符时触发
dim data as variant
dim n as long
dim sjarr() as byte
n=mscomm1.inbuffercount '接收缓冲区字符总数
if mscomm1.inputmode=0 then'文本模式时,将收到的数据放到字符串变量。
mscomm1.inputlen=0
data = space(n)
data = mscomm1.input
else '二进制模式时,将收到的数据放到字节数组。
redim s jarr(1ton)
data=arr
mscomm1.inputlen=n
data=mscomm1.input
end if
'其它case情况略
end select
end sub