AT指令之TCPIP命令
BC26 还有⼀组专⽤于 TCP 通信的 AT 指令:《BC26_TCP/IP_AT_Commands_Manual_V1.1》,之前已经有了 Socket 可以进⾏ TCP 通信,现在⼜出⼀个 TCP/IP。或许就是 C# 中的 Socket 与 TCPClient 之间的关系吧,也有可能是早期出了⼀个简单版本的可⽤于 TCP 编程的 Socket,之后⼜出⼀个功能更为强⼤的 TCP/IP,⽽为了兼容⽼程序,保留了 Socket ⽽已。总之,前⾯弄过的东西需要再来⼀遍。当然TCP/IP 指令⼀样可以⽤于 UDP 通信,本⽂就不再讲解 UDP 了。
概述(本节译⾃原⽂档)
Quectel BC26 模块嵌⼊了 TCP/IP 协议栈,它使得主机可以直接通过 AT 指令访问 Internet。这⼤⼤减少了对 PPP 和外部 TCP/IP 协议栈的依赖,从⽽将成本降到最低。
Quectel BC26 模块提供了以下 socket 服务:TCP 客户端和 UDP 客户端。
数据访问模式
BC26 模块⽀持以下两种类型的数据访问模式:
缓存访问模式
直接推送模式
当通过AT+QIOPEN打开⼀个 socket 服务,可通过参数<access_mode>来指定数据访问模式。在 socket 服务开始后,AT+QISWTMD可⽤于改变数据访问模式。
1. 在缓存访问模式中,数据可通过AT+QISEND/AT+QISENDEX指令发送。当接收到数据时,模块将缓存数据并报告⼀个 URC,格式
为:+QIURC:“recv”,<connectID>[,<current_recv_length>]。主机可使⽤AT+QIRD读取数据。
注意:在缓存访问模式中,如果缓存不为空,模块将不会报告新的 URC,直到所有收到的数据被AT+QIRD从缓存中读取。
2. 在直接推送模式中,数据可通过AT+QISEND/AT+QISENDEX指令发送。接收到的数据将直接通过以下 URC 输出:
+QIURC: “recv”,<connectID>,<current_recv_length><CR><LF><data>
命令介绍
⾸先介绍本⽂所使⽤到的命令。
AT+QIOPEN=<contextID>,<connectID>,<service_type>,<IP_address>,<remote_port><local_port>,<access_mode>
打开⼀个 Socket 服务。
<contextID>:上下⽂ ID,范围 1-3,⽤来⼲啥的我也不懂,⼀般情况下设为 1 就⾏了。
<connectID>:Socket 服务编号,其实就是之前讲过的,BC26 最多⽀持 5 个 Socket,编号 1-4。
<service_type>:协议类型,"TCP"或"UDP"。
<IP_address>:远程服务器⼗进制点分隔 IP 地址。
<remote_port>:远程服务器端⼝。
<local_port>:可以指定本地通信端⼝,⼀般设为 0,表⽰让程序⾃动分配。
<access_mode>:Socket 服务数据访问模式,0 为缓存访问模式;1 为直接推送模式。
AT+QISTATE=<query_type>,<connectID>
检查 Socket 服务的连接状态。
<query_type>:指是通过<contextID>(0)还是通过<connectID>(1)来查询连接状态。⼀般情况下都是⽤ 1,即<connectID>进⾏查询。
<connectID>:选择 5 个 socket 中的⼀个查询,范围 0-4。
AT+QISEND=<connectID>,<send_length>,<data>
向服务器发送数据。
<send_length>:发送数据的长度,以字节为单位
<data>:发送的数据
AT+QISEND=<connectID>
向服务器发送变长数据。发送此命令后,服务器会响应⼀个>,此时输⼊要发送的数据,并按快捷键【Ctrl + Z】即可发送给服务器。
AT+QISENDEX=<connectID>,<send_length>,<hex_string>
⼗六进制字符串格式发送数据,如AT+QISENDEX=0,5,3031323334,是向 0 号 Socket 发送长度为 5
的字符串“01234”。
AT+QIRD=<connectID>,<read_length>
从接收缓存中读取数据。
<read_length>:接收的长度,最⼤值为 512 字节,⼀般设置为 512 更⽅便,它会⾃动按缓存中的数据长度接收。
AT+QICFG="showlength"[,<show_length_mode>]
设置在收到服务器信息时,显⽰的 URC 中是否包含数据长度信息。
<show_length_mode>:设为 0 表⽰不显⽰,设为 1 表⽰显⽰。
AT+QICFG="viewmode"[,<view_mode>]
设置在读取接收缓存中的数据时的显⽰格式。
<view_mode>:
0:格式为:数据长度,剩余长度,数据
1:格式为:数据长度,数据
AT+QICLOSE=<connectID>
关闭连接。
AT+QPING=<contextID>,<host>
Ping ⼀个远程服务器。
<host>:远程主机域名或 IP 地址
AT+QNTP=<contextID>,<server>
从远程服务器同步时间。
<server>:远程时间服务器域名或 IP 地址。
服务器端
本⽂使⽤的例⼦较多,经常重新连接,不能再象上⼀个程序那样,每⼀个连接就要重启⼀次程序。这次程序改为可接收多个连接。
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Text;
namespace TCPSocket
{
class Program
{
static void Main(string[] args)
{ //设置服务器 IP,如果是腾讯云,必须使⽤内⽹地址,⽽不是公⽹ IP。
IPAddress ip = IPAddress.Parse("172.16.0.11");
IPEndPoint point = new IPEndPoint(ip, 5000); //端⼝指定为 5000
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.Bind(point);
//开⼀个单独的线程去侦听客户端连接
Task.Factory.StartNew(() => Listening(s), TaskCreationOptions.LongRunning);
Console.ReadLine(); //按回车关闭程序
}
//侦听线程⽅法
static void Listening(Socket s)
{
s.Listen(5);
Console.WriteLine("服务器开始侦听...");
while (true)
{
Socket subSocket = s.Accept(); //等待新连接
Console.WriteLine("获取⼀个来⾃{0}的连接", subSocket.RemoteEndPoint.ToString());
//创建线程接收客户端的消息
Task.Factory.StartNew(() => ReceiveMessage(subSocket), TaskCreationOptions.LongRunning);
}
}
//监听客户端连接的线程⽅法
static void ReceiveMessage(Socket subSocket)
{
byte[] buff = new byte[1024]; //创建⼀个接收缓冲区
try
{
while (true)
{
int count = subSocket.Receive(buff, buff.Length, SocketFlags.None);
//下⾯这个判断是⾮常必要的,否则有可能导致不停地接收到长度为 0 的数据,导致 CPU 占⽤率100%
if (count == 0)
{
subSocket.Close();
return;
}
//将接收到的数据转化为 ASCII 字符
string recvStr = Encoding.ASCII.GetString(buff, 0, count);
Console.WriteLine($"接收到数据:{recvStr}");
//将消息原样返回
subSocket.Send(buff, count, SocketFlags.None);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
subSocket.Close();//客户端关闭时会引发异常,此时关闭此连接
Console.WriteLine($"客户端{subSocket.RemoteEndPoint.ToString()}已退出连接。");
}
}
}
}
启动程序后,可以最⼩化去放⼼做实验了,重连多少次都不需要再回来看⼀眼。
缓存访问模式
BC26 ⽀持两种数据访问模式:缓存访问模式和直接推送模式。我们⾸先介绍缓存访问模式的操作。数据的发送
发送数据使⽤AT+QISEND和AT+QISENDEX两个命令。
发送定长数据
//打开 socket 服务,并指定为缓存访问模式
>>>>>>>>>> AT+QIOPEN=1,0,"TCP","193.112.19.116",5000,0,0
OK
+QIOPEN: 0,0 //URC:两个参数分别表⽰ socket 编号和错误码。
//查询⽹络状态
>>>>>>>>>> AT+QISTATE=1,0
//倒数第三个参数 2 表⽰已经连接⽹络
+QISTATE: 0,"TCP","193.112.19.116",5000,0,2,1,0
OK
//发送长度为10个字节的字符串“1234567890”
>>>>>>>>>> AT+QISEND=0,10,1234567890
OK
SEND OK
+QIURC: "recv",0 //URC:表⽰ 0 号 socket 接收到数据
//发送长度为5个字节的⼗六进制格式的字符串“01234”
>>>>>>>>>> AT+QISENDEX=0,5,3031323334
OK
SEND OK
>>>>>>>>>> AT+QICLOSE=0 //关闭 socket 服务
OK
CLOSE OK
此例使⽤两种⽅法向服务器发送数据,第⼀次是直接发送字符串,服务器返回数据,并报告 URC。第⼆次发送的是编码形式的数据,服务器返回数据但没有报告 URC,因为第⼀次接收的内容未接收,接收缓存未清空。
发送变长数据
发送变长数据需使⽤AT+QISEND=0命令,此时服务响应⼀个>,表⽰等待⽤户输⼊,⽤户在输⼊数据后,在结尾添加 0x1A 即可向服务器发送⽆需标明长度的数据。弄懂这个命令费了⼀些周折。因为⽂档写的是输⼊命令后,按下【Ctrl + Z】键,上帝啊!我想不出哪个串⼝⼯具可以使⽤【Ctrl + Z】来发送命令啊!所有编辑框⾥的【Ctrl + Z】都是⽤来 Undo 的。后来发现只要在数据的结尾加上 0x1A 发送即可,0x1A 即代表【Ctrl + Z】键。绝不能结尾加上回车(0x0D,0x0A),必须是以 0x1A 结束。
⾃⼰写⼯具的好处就在于⾃由,想加啥都⾏,当即加上此功能,版本改为 1.01。如下图左边【发送区设置】区域内添加了⼀个“⾃动添加【Ctrl+Z】”项,选择此项后,再点绿⾊按钮发送数据,就会⾃动添加 0x1A 并发送。
按上图所⽰设置接收区和发送区选项,打开 TCP Client 脚本,所有命令需要使⽤右边脚本⾯板中每条命令右边的三⾓按钮发送。仅
在AT+QISEND=0命令之后的输⼊发送数据时使⽤发送区进⾏发送。在选择“⾃动添加【Ctrl+Z】”项时,由于⽆法在命令后⾯添加回车,发送区不能发送命令。以下是完整命令脚本
>>>>>>>>>> AT+QIOPEN=1,0,"TCP","193.112.19.116",5000,0,0
OK
+QIOPEN: 0,0
>>>>>>>>>> AT+QISEND=0
>
>>>>>>>>>> www.iotxfd //注意,这⾥的结尾是 0x1A
OK
SEND OK
+QIURC: "recv",0
>>>>>>>>>> AT+QICLOSE=0
OK
CLOSE OK
在使⽤这种⽅式进⾏发送时,还可以指定基最⼤发送长度,如AT+QISEND=0,10,表⽰只发送 10 个字节。下例演⽰了这种情况:>>>>>>>>>> AT+QIOPEN=1,0,"TCP","193.112.19.116",5000,0,0
OK
+QIOPEN: 0,0
>>>>>>>>>> AT+QISEND=0,10
>
>>>>>>>>>> www.iotxfd //注意,这⾥的结尾是 0x1A
www.iotxfd //多出的字符串被截断
OK
SEND OK
+QIURC: "recv",0
>>>>>>>>>> AT+QICLOSE=0
OK
CLOSE OK
可以看到,由于指定了最⼤长度,多出来的字符串未被发送。
数据的接收
先来⼀个最简单的接收⽰例:
>>>>>>>>>> AT+QIOPEN=1,0,"TCP","193.112.19.116",5000,0,0 //创建 Socket 服务
OK
+QIOPEN: 0,0 //连接成功,使⽤的是 0 号 socket
>>>>>>>>>> AT+QISEND=0,10,1234567890 //发送字符串“01234567890”
OK
SEND OK
+QIURC: "recv",0 //URC:0 号 socket 收到信息
>>>>>>>>>> AT+QIRD=0,512 //接收 0 号 socket 的接收缓冲区,长度 512
+QIRD: 10 //收到 10 个字节
1234567890 //数据为:1234567890
OK
>>>>>>>>>> AT+QIRD=0,512 //再次接收
+QIRD: 0 //指⽰接收缓冲已空
OK
>>>>>>>>>> AT+QICLOSE=0 //关闭 socket 服务
OKtcpip协议pdf
CLOSE OK
这种接收⽅式应当是最常⽤的,每次按最⼤接收数 512 进⾏接收,最终只按实际数据长度进⾏接收,使⽤起来⾮常⽅便。你也可以指定接收的长度,如:
>>>>>>>>>> AT+QIOPEN=1,0,"TCP","193.112.19.116",5000,0,0
OK
+QIOPEN: 0,0
>>>>>>>>>> AT+QISEND=0,10,1234567890
OK
SEND OK
+QIURC: "recv",0 //URC:0 号 socket 收到信息
>>>>>>>>>> AT+QIRD=0,6 //指定接收长度为 6 个字节
+QIRD: 6 //接收了 6 个字节
123456
OK
>>>>>>>>>> AT+QIRD=0,6 //再次接收
+QIRD: 4 //接收了剩余的 4 个字节
7890
OK
>>>>>>>>>> AT+QICLOSE=0
OK
CLOSE OK
可以使⽤AT+QICFG="showlength",1指令更改收到信息 URC 的显⽰⽅式,让其指⽰收到了多少个字节。过程如下图所⽰:
可以使⽤AT+QICFG="viewmode",1更改接收信息的显⽰⽅式:
>>>>>>>>>> AT+QICFG="viewmode",0 //将接收信息显⽰⽅式改为 0
OK
>>>>>>>>>> AT+QIOPEN=1,0,"TCP","193.112.19.116",5000,0,0
OK
+QIOPEN: 0,0
>>>>>>>>>> AT+QISEND=0,10,1234567890
OK
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论