---- 过 去, 开 发 通 信 软 件 对 于 一 般 的 应 用 软 件 开 发 人 员 来 说 是 比 较 困 难 的。 而 现 在 这 件 事 已 经 变 得 容 易 多 了。 本 文 介 绍 如 何 利 用VB5.0 和MSCOMM 控 件 开 发 通 信 软 件。
---- 要 想 自 己 开 发 通 信 软 件, 除 了 要 掌 握VB5.0 的 基 本 编
程 语 言 以 外, 还 需 知 道 一 些 微 机 通 信 的 基 本 原 理。 如 有 关 串 行 端 口 及 调 制 解 调 器 的 基 本 知
识, 调 制 解 调 器 的 使 用 手 册 及AT 命 令 集 等。 这 在 许 多 书 中 都 可 以 找 到。 本 文 不 再 叙 述。
二 有 关 预 备 知 识
---- 在 PC 机 串 行 端 口 与 调 制 解 调 器 进 行 连 接 时, 有
十 几 根 线 进 行 信 号 传 输。 对 于 用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 控 件 的 属 性 及 事 件
---- VB5.0 所 带 的 通 信 控 件 MSCOMM 易 学 易 用。 它 只
有 约30 个 属 性 和 事 件。 可 以 从VB5.0 的 联 机 帮 助 中 找 到 它 的 全 部 资 料。 本 文 简 述 它 的 主 要 属 性
及 事 件, 并 加 已 归 类 整 理。 以 下 用 MSCOMM1 表 示 在 窗 体 上 设 置 的 一 个 MSCOMM 控 件 的 名 称
---- ( 一) 通 信 参 数 设 置
---- (1) CommPort 属 性
---- 语 法: MSCOMM1.CommPort [=Value]
---- 作 用: 设 置 或 返 回 联 接 MODEM 的 串 口 的 编 号。
---- 值: 用1,2, ... 表 示 串 口 COM1,COM2 ....
---- (2) Settings 属 性
---- 语 法: MSCOMM1.Settings [=Value]
---- 作 用: 设 置 或 返 回 通 信 参 数。
---- 值: String 型。 例 入 用 "19200,N,8,1" 表 示 传 输 速 率 为19200
bps, 没 有 奇 偶 校 验 位,8 位 数 据 位,1 位 停 止 位。
---- (3) Handshaking 属 性
---- 语 法: MSCOMM1.Handshaking [=Value]
---- 作 用 与 值: 设 置 或 返 回 硬 件 握 手 协 议。 指 的 是PC 机MODEM
之 间 为 了 控 制 流 速 而 约 定 的 内 部 协 议。
---- 0 没 有 握 手 协 议。 不 考 虑 流 量 控 制。
---- 1 XON/XOFF。 即 在 数 据 流 中 嵌 如 控 制 苻 来 进 行 流 控。
---- 2 RTS/CTS 。 既 由 信 号 线RTS/CTS 自 动 进 行 流 量 控 制。
---- 3 两 者 皆 可。
---- 注: 实 践 中 我 们 发 现 选 用 2( 即RTS/CTS) 是 很 方 便 的。
---- ( 二) 打 开/ 关 闭 端 口
---- (4) PortOpen 属 性
---- 语 法: MSCOMM1.PortOpen [=Value]
---- 作 用: 打 开 或 关 闭 端 口。
---- 值: Boolean 型。 设 为 True/False 可 以 打 开/ 关 闭 端 口。
---- ( 三) 发 送 数 据
---- (5) OutBufferSize 属 性
---- 语 法: MSCOMM1.OutBufferSize [=Value]
---- 作 用: 设 置 或 返 回 传 输 缓 冲 区 大 小。
---- 值: Integer 型。 传 输 缓 冲 区 的 字 节 数。 例 如 可 选 1024
。
---- (6) OutPut 属 性
---- 语 法: MSCOMM1.OutPut [=Variant]
---- 作 用: 向 传 输 缓 冲 区 写 数 据 流。
---- 值: Variant 型 变 量。
---- 注: 传 输 文 本 数 据 时, 应 将 String 型 数 据 放 入 Variant
变 量, 传 输 二 进 制 数 据( 即 按 字 节) 时, 应 将 Byte 型 数 组 数 据 放 入 Variant 变 量
---- ( 四) 接 收 数 据
---- (7) InBufferSize 属 性
---- 语 法: MSCOMM1.InBufferSize [=Value]
---- 作 用: 设 置 或 返 回 接 收 缓 冲 区 大 小。
---- 值: Integer 型。 接 收 缓 冲 区 的 字 节 数。 例 如 可 选 1024
。
---- (8) InputMode 属 性
---- 语 法: MSCOMM1.InputMode [=Value]
---- 作 用: 设 置 或 返 回 接 收 数 据 的 数 据 类 型。
---- 值: 0 用Input 属 性 接 收 文 本 型 数 据。
---- 1 用Input 属 性 接 收 二 进 制 数 据。
---- (9) InBufferCount 属 性
---- 语 法: MSCOMM1.InBufferCount [=Value]
---- 作 用: 返 回 接 收 缓 冲 区 中 已 传 到 但 还 未 取 走 的 字 符 个 数。
---- 值: Integer 型。
---- (10) Input 属 性
---- 语 法: MSCOMM1.Input [=Variant]
---- 作 用: 将 接 收 缓 冲 区 中 收 到 的 数 据 读 入 变 量。
---- 值: Variant 型 变 量。
---- 注: 当InputMode 属 性 值 为 0( 文 本 模 式) 时, 变 量 中 含 String
型 数 据。
---- 当InputMode 属 性 值 为 1( 二 进 制 模 式) 时, 变 量 中 含
Byte 型 数 组 数 据。
---- ( 五) 状 态 控 制
---- (11) DTREnabled 属 性
---- (12) RTSEnabled 属 性
---- (13) DSRHolding 属 性
---- (14) CTSHolding 属 性
---- (15) CDHolding 属 性
---- 以 上 五 个 属 性 即 如 二 所 述, 均 取 值 TRUE/FALSE, 用 于 读 取 或 控 制 pc 机 与 modem 之 间 的 交 互 状 态。 需 运 用 好。 例 如, 应 在 读 取 到 DSRHolding 属 性 值 为TRUE 时 再 向 MODEM 发 出 命 令。 应 当 在 载 波 检 测 到 以 后(CDHolding 属 性 为 TRUE) 时 再 向MODEM 发 送 数 据。
---- ( 六) 事 件
---- 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 时: 检 测 到 振 铃 信 号 .
---- 另 外 十 个 情 况 是 可 能 发 生 的 各 种 通 信 错 误 时 触 发。
可 参 看 有 关 资 料.
四 通 信 软 件 参 数 设 置
---- 在 自 己 编 写 的 通 信 软 件 中, 应 包 含 进 行 通 信 参
数 设 置 的 功 能。 主 要 就 是 可 以 设 置 端 口 号, 波 特 率, 数 据 位, 停 止 位, 奇 偶 校 验 位 及 设 置 硬 件 握
手 协 议。
---- 可 在 一 个 窗 体 上 用 下 拉 列 表 框, 选 择 钮 等 由 用 户 来
选 择。《 保 存》 时, 利 用VB5.0 的 Settings 函 数 将 这 些 参 数 存 储 在WINDOWS 95 的 系 统 注 册 表
中。 每 次 运 行 该 软 件 时, 先 用 GetSettings 函 数 调 出 这 些 参 数, 并 对Commport,Settings,Handshaking
等 属 性 赋 值, 来 进 行 通 信 参 数 设 置。
五 打 开 通 信 端 口
---- 在 编 写 的 通 信 软 件 的 主 窗 体 上, 可 以 安 排 一 个
打 开/ 关 闭 端 口 的 菜 单 项 或 图 形 按 钮。 在 打 开 端 口 时, 可 向 MODEM 发 出 命 令, 进 行 MODEM 参 数
设 置。 可 以 象 下 面 这 样 来 编 程:
'(1)打开/关闭端口 MSComm1.PORTOPEN = Not MSComm1.PORTOPEN '(2)向 MODEM 发出 DTR(已准备好) 信号----- OpenFlag = MSComm1.PORTOPEN If OpenFlag Then MSComm1.DTREnable = True Else MSComm1.DTREnable = False End If '(3)打开时向 MODEM 发出一些命令来设置参数 'S0=n (n>=1)自动应答. n为响铃次数 'E0/E1 关闭/打开命令字符回应 'Q0/Q1 modem返回/不返回结果码 'M0/M1 关闭/打开MODEM扬声器. If OpenFlag Then L1: If MSComm1.CTSHolding Then Outstring = "AT S0=1 E1 Q0 M0 " + Chr(13) MSComm1.Output = Outstring GoTo LL Else GoTo L1 End If End If '----- LL: ...---- 也 可 以 安 排 一 些 可 变 换 颜 色 的 指 示 灯 来 代 表 端 口 打 开 状 态,CD 线 状 态 等, 这 样 更 形 象 生 动。
---- 其 中 TEXT1 是 窗 体 上 让 用 户 输 入 电 话 号 的 文 本 框。
---- 为 了 使 程 序 功 能 更 强 一 些, 可 以 增 加< 电 话 号 码
簿 管 理>, 可 以 增 加, 修 改, 删 除, 查 询 电 话 号 码。 这 与 一 般 的 数 据 库 应 用 程 序 是 一 样 的。
七 发 送 文 件
---- 拨 号 以 后, 程 序 要 循 环 等 待 并 随 时 判 定 是 否 接
通。 如 果 MODEM 向 PC 的 回 应 字 符 串 中 含 有 "Connect " 或 CDHolding 属 性 值 变 为 True ( 检
测 出 载 波), 则 表 示 已 与 远 方MODEM 连 机 了。 这 时 就 可 以 发 送 文 件 了。
---- 发 送 文 件 开 始 以 前, 可 打 开 一 个 显 示 发 送 信 息 的 窗 口。 可 在 此 窗 口 上 显 示 要 发 送 的 文 件 名, 总 长 度, 已 发 送 长 度 等 信 息。
---- 设 置 以 下 全 局 变 量, 存 放 标 志 字 符 串, 在 发 送 及 接 收 程 序 中 均 使 用。
S_FILENAME = "FILENAME" + Chr(5) + Chr(13) + Chr(10) S_FILELEN = "FILELEN " + Chr(5) + Chr(13) + Chr(10) S_FILESTAR = "FILESTAR" + Chr(5) + Chr(13) + Chr(10)---- (1) 打 开 文 件:
---- 要 想 把 一 个 文 件 的 全 部 字 节 都 传 送, 需 以 二 进 制 方
式 打 开 文 件。 可 用 如 下 语 句
---- ' 得 到 下 一 个 可 用 的 文 件 号, 放 在 整 型 变 量 hSend
---- hSend = FreeFile
---- ' 打 开 文 件
---- Open SENDFN For Binary Access Read As hSend
---- LF& = LOF(hSend) ' 文 件 长 度 为 LF&
---- 其 中 变 量 SENDFN 中 含 有 由 用 户 选 定 的 要 传 送 的 文 件
名。
---- (2) 发 送 文 件 名, 文 件 长 度, 文 件 开 始 等 信 息 字 符 串。
---- 例 如, 我 们 设 计 成 如 下:
DIM VARC AS VARIANT VARC = S_FILENAME MSComm1.Output = VARC '发出 "FILENAME" 提示字串 VARC = SENDFN + Chr(13) + Chr(10) TXRJ.MSComm1.Output = VARC '发出文件名 VARC = S_FILELEN MSComm1.Output = VARC '发出 "FILELEN" 提示字串 VARC = Trim(Str(LF&)) + Chr(13) + Chr(10) MSComm1.Output = VARC '发出文件宽度 VARC = S_FILESTAR '发出 "FILESTART" 提示字串,表示下面文件开始。 MSComm1.Output = VARC 然后程序倒计时,在发送信息窗口显示 8,7,6,5,4,3,2,1,0 .---- (3) 发 送 文 件 内 容
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 '累加计数 Label6.Caption = Str(Sum) '显示在发送窗口上 Else If Timer < T Then GoTo L '循环等待 Else GoTo CLOSEFILE '等待时间超过 60秒则退出 End If End If ' 等待系统处理完 Do RET = DoEvents() Loop Until MSComm1.OutBufferCount = 0 Loop '循环语句结尾---- 文 件 发 送 完 毕 以 后, 关 闭 该 文 件。 并 关 闭 发 送 文 件 信 息 窗 口。
Private Static Sub MSComm1_OnComm() Select Case MSComm1.CommEvent Case comEvReceive '接收缓冲区收到Rthreshold个字符时触发 Dim VARC As Variant Dim N As Long Dim SJARR() As Byte ' N = MSComm1.InBufferCount '接收缓冲区字符总数 If MSComm1.InputMode = 0 Then '当输入模式为文本模式时,将收到的数据放到字符串变量。 MSComm1.InputLen = 0 VARC = Space(N) VARC = MSComm1.Input Else '当输入模式为二进制模式时,将收到的数据放到字节数组。 ReDim SJARR(1 To N) VARC = ARR MSComm1.InputLen = N VARC = MSComm1.Input End If ShowDATA TextTerm, N, VARC '调接收数据处理过程Showdata End Select End Sub---- (三) 接 收 数 据 处 理 过 程 ShowData
Public Static Sub ShowData(Term As Control, _ N As Long, DATA As Variant) '参数:Term (主窗体上的文本框,用于显示接受数据) ' N 为本次接收到的字节数 ' DATA (接收到的数据.Variant型 ) (变量定义部分:略) '(一) 非文件传输情形(接收的是字符串) If not mscomm1.InputMode= 0 Then GoTo L2 End If '(1)把新接收的字符数据放到文本框TERM末尾 Term.SelStart = Len(Term.Text) Term.SelLength = 0 Term.SelText = DATA '(2)未找到文件传输开始标志就结束此过程---- W_FILESTAR = InStr(1, Term.Text, S_FILESTAR, 0) If W_FILESTAR = 0 Then Exit Sub End If '(3)以下为找到文件传输开始标志的情况 '(3-1) 找文件名及文件长度 W_FILENAME = InStr(1, Term.Text, S_FILENAME, 0) W_FILELEN = InStr(1, Term.Text, S_FILELEN, 0) FN = Mid(Term.Text, W_FILENAME + 11, (W_FILELEN - W_FILENAME - 13)) ' (3-2)打开接收文件 hJS = FreeFile JSFN = Pathc + "\SJFILE\S" + Trim(Str(NO)) + "_" + FN Open JSFN For Binary Access Write As hJS '(3-3)收件箱增加新记录 W_FILENAME = InStr(1, Term.Text, S_FILENAME, 0) W_FILELEN = InStr(1, Term.Text, S_FILELEN, 0) FN = Mid(Term.Text, W_FILENAME + 11, (W_FILELEN - 1) - (W_FILENAME + 11)) FL = Mid(Term.Text, W_FILELEN + 11, W_FILESTAR - (W_FILELEN + 10)) SENDLEN = Val(FL) '应收总字节数SENDLEN '以下SJRS是已打开的收件箱对应的记录集型变量 SJRS.AddNew '增加一新记录 SJRS!SJRQ = Now '写入收件日期 SJRS!SJFILE = FN '写入收件的文件名 SJRS!SJLEN = Val(FL) '写入收件的长度 SJRS!FILENO = NO '写入收件的序号 '(3-4)显示文件接收窗口 JSLEN = 0 TXINPUT.Show '(3-5)改变输入模式属性 InputMode为二进制模式 TXRJ.MSComm1.InputMode = comInputModeBinary '(7)等待几秒, 显示 8 7 6 5 4 3 2 1 0 Exit Sub '(二)文件传输状态处理------------ L2: ReDim JSARR(0 To N - 1) JSARR = DATA '将字节流放入字节型数组 '将字节型数组中的数据写入已打开的接收文件 Put hJS, , JSARR JSLEN=JSLEN+N ’本次已累计收到的字节数 ' 已收字节数与文件总长相比较 If JSLEN < SENDLEN Then Exit Sub End If ' 转此为文件传输已结束------ '关闭接收文件 Close hJS '提交收件箱表的新增记录 SJRS.Update '修改文本显示 W_FILENAME = InStr(1, Term.Text, S_FILENAME, 0) Term.SelStart = W_FILENAME - 1 Term.SelLength = Len(Term.Text) Term.SelText = "" FL = "文件" + FN + "接收结束" + Chr(13) + Chr(10) Term.Text = Term.Text & FL '关闭收件窗口 Unload TXINPUT '改变 InputMode属性为文本模式 TXRJ.MSComm1.InputMode = 0 Exit Sub End Sub---- 以 上 以 发 送 和 接 收 文 件 为 例 介 绍 了 我 们 是 如 何 使 用VB5.0 及MSCOMM 控 件 来 开 发 自 己 的 的 通 信 软 件 的。 掌 握 了 以 上 基 本 技 术, 就 可 以 稍 加 改 变 来 开 发 自 己 的 各 种 专 用 通 信 软 件。 例 如 发 送 数 据 库 的 一 条 记 录, 并 使 接 收 方 把 接 收 到 的 数 据 也 放 在 数 据 库 中。 也 可 以 进 行 数 据 加 密/ 解 密 传 输 等。 总 之, 学 习 怎 样 使 用VB5.0 及MSCOMM 控 件 来 开 发 自 己 的 的 通 信 软 件 是 十 分 有 用 的。
---- 附 注: 本 软 件 运 行 环 境