使用Socket编程访问IP 串口 一.简介 在很多情况下,用户希望自己通过Socket函数编写程序访问LIANDA 。因为Socket 函 数几乎所有操作系统都支持,所以使用Socket 访问LIANDA 具有良好的跨平台性,另外使 用Socket 函数要比Windows 下或Unix的串口访问函数简单的多的多,还有,几乎所有编写 过网络程序的程序员都会使用Socket 函数。之所以提供COM 口和TTY 口的驱动的主要目的 是为了让LIANDA 直接支持户以前编写的基于串口的应用程序。我们鼓励基于LIANDA 开发 新应用程序的用户使用Socket函数访问LIANDA 。 二.配置命令SCKCFG sckcfg [N] [-m MODE] [-rip R_IP] [-rt R_PORT] [-lt L_PORT] [-c CONN] [-cs CSEQ] [-scs SCSEQ] [-d DISC][-ds DSEQ] [-sds SDSEQ] [-k KEEPALV] [N] 对应设备上串口号,支持X-Y批量设置 -m MODE 工作模式,取值tc|ts|u tc - TCP 客户端模式 ts - TCP 服务器端模式 u - UDP 模式 -rip R_IP 远端主机IP地址 -rt R_PORT 远端主机TCP/UDP 端口号 -lt R_PORT 本地设备(LIANDA )TCP/UDP 端口号 -c CONN 初始化连接方式取值n | dcdon | dsron | seq | brk n - 从不初始化连接 dcdon - 当DCD信号为高时,初始化连接 dsron - 当DSR 信号为高时,初始化连接 seq - 当收到CSEQ(见下-cs),初始化连接 brk - 当收到BREAK 信号,初始化连接 -cs CSEQ 指定串口接收到的初始化连接的序列,取值范围为十六进制数“0-9”“A-F” -scs SCSEQ 收到CSEQ 后是否发送CSEQ 给主机,取值1|0 1 - 发送CSEQ 0 - 不发送CSEQ -d DISC 关闭连接方式,取值n | dcdoff | dsroff | seq | brk n - 从不关闭连接 dcdoff – 当DCD信号为低时,关闭连接 dsroff – 当DSR 信号为低时,关闭连接 seq - 当收到DSEQ(见下–ds), 关闭连接 brk - 当收到BREAK 信号,关闭连接 -ds DSEQ 指定串口接收到的关闭连接的序列,取值范围为十六进制数“0-9”“A-F” -sds SCSEQ 收到DSEQ 后是否发送DSEQ 给主机,取值1|0 1 - 发送DSEQ 0 - 不发送DSEQ -k KEEPALV 以秒计的SOCKET保活时间,取值范围0-10000,0 表示无效 注意事项: 1. 子选项-rip和-rt分别配置了主机端的IP地址和端口号.当工作模式为tc或u 时,两者合起来建立主机端的 SOCKET.当工作模式为ts 时, 两者若有配置值,表示只能由它们建立的SOCKET 才可以访问LIANDA 的这个串口, 否则不加限制. 2. 子选项-lt 配置了设备端(LIANDA )的端口号, 它和LIANDA 的IP 地址合起来建立设备端的SOCKET.当工作模 LD-16XX系列串口服务器使用Socket编程北京联达科讯科技有限公司 http://www. 电话:010-67271834 传真:010-52201605 2 式为tc 是无效,工作模式为ts 或u时有效. 3. 子选项-c 配置初始化连接方式.它当工作在tc 的模式下时,在何种条件下LIANDA 去发起连接.其中当配置值 为seq 时,就必须配置后面的-cs 和-scs 这两个子选项, 否则这两个子选项无效. 4. 子选项-d 配置关闭连接方式.它表示在何种条件下LIANDA 主动去关闭连 接.其中当配置值为seq 时,就必须配置后面的-ds 和-sds 这两个子选项, 否则这两个子选项无效. 5. –k 子选项配置的保活时间值,是对设备(LIANDA )而言.主机端程序的保活处理必须在程序程序中另做处理. 三.工作模式 LIANDA 共有三种SOCKET访问模式: 1. TCP SERVER模式 在这种模式下,LIANDA 处于Listen 状态,监听的端口号是命令SCKCFG 中子选项–lt的配置值. 2.TCP CLIENT模式 在这种模式下,LIANDA 主动发起连接.LIANDA 所要连接的主机的IP 地址和端口号分别是命令SCKCFG中子选项 -rip和-rt的值. 3.UDP模式 在这种模式下,LIANDA 处于UDP server/client状态.LIANDA 端的SOCKET绑定(bind)在值为SCKCFG 中子选项-lt 的配置参数的端口上.对等端的SOCKET 则绑定在IP 地址为RIP的主机的端口RPORT上. (其中RIP和RPORT分别为命令SCKCFG 中子选项-rip和-rt的值) 四.协议包格式 注意事项: 1. 命令和数据使用同一个SOCKET 2. 命令以0xff开头, 数据中的0xff转换为连续的两个0xff 命令: 1. SET_SERIAL(设置串口参数) (0x01), 主机发 0xff 0x01 Mask Mode Flow Ctrl Baud 1 1 1 1 1 1 4 MASK : Bit 0 MASK_BAUD Bit 1 MASK_MODE Bit 2 MASK_FLOW Bit 3 MASK_BRK Bit 4 MASK_CTRL Bit 5 ~ bit 7 UNUSED MODE : DATA BITS | STOP BITS | PARITY | BREAK DATA BITS (bit 0, 1) = 0x00 = CS5 0x01 = CS6 0x02 = CS7 0x03 = CS8 STOP BITS (bit 2) = 0x00 = STOP1 0x04 = STOP2 or STOP1.5(only whendata bits is CS5) PARITY (bit 3,4 5) = 0x00 = PAR_NONE 0x08 = PAR_ODD 0x18 = PAR_EVEN 0x28 = PAR_MARK 0x38 = PAR_SPACE LD-16XX系列串口服务器使用Socket编程北京联达科讯科技有限公司 http://www. 电话:010-67271834 传真:010-52201605 3 BREAK(bit 6) 0x00 = CLEAR BREAK 0x40 = SET BREAK bit7 UNUSED FLOW : Bit 0 : OUT_CTS Bit 1 : OUT_DSR Bit 2 : OUT_X Bit 3 : OUT_XANY Bit 4 : IN_RTS Bit 5 : IN_DTR Bit 6 : IN_X Bit 7 : UNUSED CTRL : DTR | RTS DTR (bit 0) 0 : 0FF, 1 : ON RTS (bit 1) 0 : OFF, 1 : ON BAUD : LOW WORD : hign bits of real baud HIGH WORD : low bits of real baud 2. SET_REPORT(设置LIANDA 报告串口状态的方式) (0x02) , 主机发 0xff 0x02 TYPE 1 1 1 TYPE : 0 : ONCE 1 : IF CHANGED 2 : TIMER (时间间隔是1 second) 3. REPORT_SERIAL (LIANDA 设备报告状态) (0x03), 主机收 0xff 0x03 DATA 1 1 2 DATA : 1ST BYTE: BIT0 S_CTS BIT1 S_DSR BIT2 S_RI BIT3 S_DCD BIT4-7 UNUSED 2nd BYTE: unsigned long baud; unsigned char buf[10]; mode = CS8 | STOP1 | PAR_NONE; // 8 bits data, 1 bit stop, no parity flow = FLOW_NONE; // no flowctrl ctrl = C_DTR | C_RTS; // DTR on, RTS on baud = 9600; // baud is 9600bps mask = MASK_MODE | MASK_FLOW | MASK_CTRL | MASK_BAUD; buf[0] = 0xff; buf[1] = NSER_CMD_SET_SERIAL; LD-16XX系列串口服务器使用Socket编程北京联达科讯科技有限公司 http://www. 电话:010-67271834 传真:010-52201605 7 buf[2] = mask; buf[3] = mode; buf[4] = flow; buf[5] = ctrl; *((unsigned short *)(buf + 6)) = (unsigned short)((baud >> 16) & 0xffff); *((unsigned short *)(buf + 8)) = (unsigned short)(baud & 0xffff); send(fd, (char *)buf, 10, 0); } b. SET_REPORT void set_report(int fd) { unsigned char type; unsigned char buf[3]; type = REPORT_IF_CHANGED; buf[0] = 0xff; buf[1] = NSER_CMD_SET_REPORT; buf[2] = type; send(fd, (char *) buf, 3, 0); } c. TIME_BREAK void send_time_break(int fd) { unsigned char buf[6]; unsigned long brktm; brktm = 1000; // 1 秒 buf[0] = 0xff; buf[1] = NSER_CMD_TIME_BREAK; *((unsigned short *)(buf + 2)) = (unsigned short)((brktm >> 16) & 0xffff); *((unsigned short *)(buf + 4))= (unsigned short)(brktm & 0xffff); send(fd, (char *)buf, 6, 0); } d. CLOSE void send_close(int fd) { unsigned char buf[2]; buf[0] = 0xff; buf[1] = NSER_CMD_CLOSE; send(fd, (char *)buf, 2, 0); } e. KEEPALIVE void send_keepalive(int fd) { unsigned char buf[2]; buf[0] = 0xff; LD-16XX系列串口服务器使用Socket编程北京联达科讯科技有限公司 http://www. 电话:010-67271834 传真:010-52201605 8 buf[1] = 0xf1; send(fd, (char *)buf, 2, 0); } 4. 数据的发送(以TCP SOCKET 为例, UDP SOCKET 中把函数send改为sendto) 注: fd是已建立好的SOCKET sendbuf 为待发送的数据缓冲 sendlen 为待发送的数据长度 int i; for (i = 0; i < sendlen; i++) { if (sendbuf[i] == 0xff) { n = send(fd, "\0xff\0xff", 2, 0); // send two continuous 0xff } else { n = send(fd, sendbuf[i], 1, 0); } } 5.数据的接收(以TCP SOCKET 为例, UDP SOCKET 中把函数recv改为recvfrom) 注: fd是已建立好的SOCKET char recvbuf[1024]; int recvlen, n; int has_a_ff = 0; // if have receive a 0xff recvlen = recv(fd, recvbuf, 1024, 0); for (n = 0; n < recvlen; n++) { if (recvbuf[n] == 0xff) { has_a_ff += 1; has_a_ff &= 0x01; if (has_ff == 0) { // 得到连续的两个0xff, 代表一个数据0xff } } if (has_ff) { switch(recvbuf[n]) { case REPORT_SERIAL: // receive command REPORT_SERIAL break; default: break; } } // DATA } |
|