|
楼主 |
发表于 2017-11-1 14:43:06
|
显示全部楼层
14.2 TCP客户端API函数
使用如下12个函数可以实现RL-TCPnet的TCP通信:
(1)tcp_get_socket
(2)tcp_connect
(3)tcp_listen
(4)tcp_close
(5)tcp_abort
(6)tcp_release_socket
(7)tcp_get_buf
(8)tcp_max_dsize
(9)tcp_send
(10)tcp_get_state
(11)tcp_check_send
(12)tcp_reset_window
关于这12个函数的讲解及其使用方法可以看教程第 3 章 3.4 小节里面说的参考资料 rlarm.chm 文件:
这里我们重点的说以下7个函数,因为本章节配套的例子使用的是这 7 个函数:
(1)tcp_get_socket
(2)tcp_connect
(3)tcp_check_send
(4)tcp_max_dsize
(5)tcp_get_buf
(6)tcp_send
(7)tcp_get_state
关于这些函数注意以下两点:
1、这些函数都不支持重入,也就是不支持多任务调用。
2、TCP接口函数通过TCP Socket做数据传输,主要用于数据安全作为首选的场合。TCP Socket发送完毕数据后会等待应答,任何数据包失败都会重传。
14.2.1 函数tcp_get_socket
函数原型:
- U8 tcp_get_socket (
- U8 type, /* TCP Socket类型 */
- U8 tos, /* TCP服务类型 */
- U16 tout, /* 断开连接前的空闲溢出时间 */
- U16 (*listener)( /* 回调函数 */
- U8 socket, /* Socket句柄 */
- U8 event, /* TCP事件 */
- U8* ptr, /* 记录接收到的数据或者远程机器的IP地址 */
- U16 par )); /* 记录接收到的数据长度或者远程机器的端口号 */ [size=3][font=新宋体] [/font][/size]
复制代码 函数描述:
函数tcp_get_socket用于获取一个TCP Socket。
(1)第1个参数是TCP Socket的类型。
(2)第2个参数用于指定服务类型,默认取零即可。
(3)第3个参数用于设置空闲溢出时间,单位秒。Keep alive定时器用于监控TCP连接,如果连接的空闲时间(也就是长时间没有数据通信)超出了,那么会断开连接。如果设置了TCP_TYPE_KEEP_ALIVE属性,会通过发送keep alive数据包来保持连接。
(4)第4个参数是回调函数,用于事件监听。
a. 回调函数第1个参数,TCP Socket的句柄,也就是函数tcp_get_socket的返回值。
b. 回调函数第2个参数,事件类型。
c. 回调函数第3个参数,事件类型是TCP_EVT_DATA,ptr指向的缓冲区记录着接收到的TCP数据,其余事件记录IP地址。
d. 回调函数第4个参数,记录接收到的数据个数,其余事件记录端口号。
(5)返回值,如果获取成功,返回TCP Socket句柄,如果获取失败,返回0。
使用这个函数要注意以下问题:
1. 调用TCPSocket任何其它函数前,务必要调用此函数tcp_get_socket。
2. 使用函数tcp_get_socket,第四个参数的监听回调函数务必要设置。
3. 如果需要长时间连接,需要设置属性TCP_TYPE_KEEP_ALIVE。
使用举例:
- /*
- *********************************************************************************************************
- * 宏定义,远程服务器的IP和端口
- *********************************************************************************************************
- */
- /* 要访问的远程服务器IP和端口配置,也就是电脑端调试助手设置的IP和端口号 */
- #define IP1 192
- #define IP2 168
- #define IP3 1
- #define IP4 2
-
- #define PORT_NUM 1001
-
- /* 这个是本地端口 */
- #define LocalPort_NUM 1024
-
-
- /*
- *********************************************************************************************************
- * 变量
- *********************************************************************************************************
- */
- uint8_t socket_tcp;
- uint8_t Rem_IP[4] = {IP1,IP2,IP3,IP4};
-
-
- /*
- *********************************************************************************************************
- * 函 数 名: tcp_callback
- * 功能说明: TCP Socket的回调函数
- * 形 参: soc TCP Socket类型
- * evt 事件类型
- * ptr 事件类型是TCP_EVT_DATA,ptr指向的缓冲区记录着接收到的TCP数据,其余事件记录IP地址
- * par 事件类型是TCP_EVT_DATA,记录接收到的数据个数,其余事件记录端口号
- * 返 回 值:
- *********************************************************************************************************
- */
- U16 tcp_callback (U8 soc, U8 evt, U8 *ptr, U16 par)
- {
- char buf[50];
- uint16_t i;
-
- /* 确保是socket_tcp的回调 */
- if (soc != socket_tcp)
- {
- return (0);
- }
-
- switch (evt)
- {
- /*
- 远程客户端连接消息
- 1、数组ptr存储远程设备的IP地址,par中存储端口号。
- 2、返回数值1允许连接,返回数值0禁止连接。
- */
- case TCP_EVT_CONREQ:
- sprintf(buf, "远程客户端请求连接IP: %d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);
- printf_debug("IP:%s port:%d\\r\\n", buf, par);
- return (1);
-
- /* 连接终止 */
- case TCP_EVT_ABORT:
- break;
-
- /* Socket远程连接已经建立 */
- case TCP_EVT_CONNECT:
- printf_debug("Socket is connected to remote peer\\r\\n");
- break;
-
- /* 连接断开 */
- case TCP_EVT_CLOSE:
- printf_debug("Connection has been closed\\r\\n");
- break;
-
- /* 发送的数据收到远程设备应答 */
- case TCP_EVT_ACK:
- break;
-
- /* 接收到TCP数据帧,ptr指向数据地址,par记录数据长度,单位字节 */
- case TCP_EVT_DATA:
- printf_debug("Data length = %d\\r\\n", par);
- for(i = 0; i < par; i++)
- {
- printf_debug("ptr[%d] = %d\\r\\n", i, ptr[i]);
- }
- break;
- }
-
- return (0);
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: TCPnetTest
- * 功能说明: TCPnet应用
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void TCPnetTest(void)
- {
- uint8_t res;
-
- /*
- 创建TCP Socket并连接,客户端连接服务器后,10秒内无数据通信将断开连接。
- 但是由于这里使能了TCP_TYPE_KEEP_ALIVE,会一直保持连接,不受10秒的时间限制。
- */
- socket_tcp = tcp_get_socket (TCP_TYPE_CLIENT | TCP_TYPE_KEEP_ALIVE, 0, 10, tcp_callback);
- if(socket_tcp != 0)
- {
- res = tcp_connect (socket_tcp, Rem_IP, PORT_NUM, LocalPort_NUM);
- printf("TCP Socket创建成功res = %d\\r\\n", res);
- }
-
- while (1)
- {
- /* 省略 */
- }
- }
复制代码
14.2.2 函数tcp_connect
函数原型:
- BOOL tcp_connect (
- U8 socket, /* Socket 句柄 */
- U8* remip, /* 远程IP地址 */
- U16 remport, /* 远程端口号 */
- U16 locport ); /* 本地端口号 */ [size=3][font=新宋体] [/font][/size]
复制代码 函数描述:
函数tcp_connect用于连接远程TCP服务器。
(1)第1个参数是要设置监听的TCP Socket句柄。
(2)第2个参数是远程服务器IP。
(3)第3个参数是远程服务器端口号。
(4)第4个参数是本地端口号。如果此参数设置为0,RL-TCPnet自动为其分配未使用的TCP端口号。
(5)返回值,成功开启连接返回__TRUE(注意,并不是已经建立了连接),否则返回__FALSE。
使用这个函数要注意以下问题:
1. 只有创建的TCP客户端才可以使用此函数,也就是调用函数tcp_get_socket的第一个形参必须得是TCP_TYPE_CLIENT 或者 TCP_TYPE_CLIENT_SERVER。
使用举例:
- /*
- *********************************************************************************************************
- * 宏定义,远程服务器的IP和端口
- *********************************************************************************************************
- */
- /* 要访问的远程服务器IP和端口配置,也就是电脑端调试助手设置的IP和端口号 */
- #define IP1 192
- #define IP2 168
- #define IP3 1
- #define IP4 2
-
- #define PORT_NUM 1001
-
- /* 这个是本地端口 */
- #define LocalPort_NUM 1024
-
-
- /*
- *********************************************************************************************************
- * 变量
- *********************************************************************************************************
- */
- uint8_t socket_tcp;
- uint8_t Rem_IP[4] = {IP1,IP2,IP3,IP4};
-
-
- /*
- *********************************************************************************************************
- * 函 数 名: tcp_callback
- * 功能说明: TCP Socket的回调函数
- * 形 参: soc TCP Socket类型
- * evt 事件类型
- * ptr 事件类型是TCP_EVT_DATA,ptr指向的缓冲区记录着接收到的TCP数据,其余事件记录IP地址
- * par 事件类型是TCP_EVT_DATA,记录接收到的数据个数,其余事件记录端口号
- * 返 回 值:
- *********************************************************************************************************
- */
- U16 tcp_callback (U8 soc, U8 evt, U8 *ptr, U16 par)
- {
- char buf[50];
- uint16_t i;
-
- /* 确保是socket_tcp的回调 */
- if (soc != socket_tcp)
- {
- return (0);
- }
-
- switch (evt)
- {
- /*
- 远程客户端连接消息
- 1、数组ptr存储远程设备的IP地址,par中存储端口号。
- 2、返回数值1允许连接,返回数值0禁止连接。
- */
- case TCP_EVT_CONREQ:
- sprintf(buf, "远程客户端请求连接IP: %d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);
- printf_debug("IP:%s port:%d\\r\\n", buf, par);
- return (1);
-
- /* 连接终止 */
- case TCP_EVT_ABORT:
- break;
-
- /* Socket远程连接已经建立 */
- case TCP_EVT_CONNECT:
- printf_debug("Socket is connected to remote peer\\r\\n");
- break;
-
- /* 连接断开 */
- case TCP_EVT_CLOSE:
- printf_debug("Connection has been closed\\r\\n");
- break;
-
- /* 发送的数据收到远程设备应答 */
- case TCP_EVT_ACK:
- break;
-
- /* 接收到TCP数据帧,ptr指向数据地址,par记录数据长度,单位字节 */
- case TCP_EVT_DATA:
- printf_debug("Data length = %d\\r\\n", par);
- for(i = 0; i < par; i++)
- {
- printf_debug("ptr[%d] = %d\\r\\n", i, ptr[i]);
- }
- break;
- }
-
- return (0);
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: TCPnetTest
- * 功能说明: TCPnet应用
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void TCPneint8_t res;
- tTest(void)
- {
- /*
- 创建TCP Socket并连接,客户端连接服务器后,10秒内无数据通信将断开连接。
- u
- 但是由于这里使能了TCP_TYPE_KEEP_ALIVE,会一直保持连接,不受10秒的时间限制。
- */
- socket_tcp = tcp_get_socket (TCP_TYPE_CLIENT | TCP_TYPE_KEEP_ALIVE, 0, 10, tcp_callback);
- if(socket_tcp != 0)
- {
- res = tcp_connect (socket_tcp, Rem_IP, PORT_NUM, LocalPort_NUM);
- printf("TCP Socket创建成功res = %d\\r\\n", res);
- }
-
- while (1)
- {
- /* 省略 */
- }
- }
复制代码
14.2.3 函数tcp_check_send
函数原型:
- BOOL tcp_check_send (
- U8 socket ); /* TCP socket 句柄 */ [size=3][font=新宋体] [/font][/size]
复制代码 函数描述:
函数tcp_check_send用于检测是否可以发送数据。此函数通过检测TCP连接是否建立以及上次发送的数据是否接收到远程机器的应答来判断是否可以发送数据。
(1)第1个参数是TCP Socket句柄。
(2)返回值,可以发送数据,返回__TRUE;不可以发送数据,返回__FALSE。
使用举例:
- /*
- *********************************************************************************************************
- * 宏定义,远程服务器的IP和端口
- *********************************************************************************************************
- */
- /* 要访问的远程服务器IP和端口配置,也就是电脑端调试助手设置的IP和端口号 */
- #define IP1 192
- #define IP2 168
- #define IP3 1
- #define IP4 2
-
- #define PORT_NUM 1001
-
- /* 这个是本地端口 */
- #define LocalPort_NUM 1024
-
- /*
- *********************************************************************************************************
- * 变量
- *********************************************************************************************************
- */
- uint8_t socket_tcp;
- uint8_t Rem_IP[4] = {IP1,IP2,IP3,IP4};
-
-
- /*
- *********************************************************************************************************
- * 函 数 名: tcp_callback
- * 功能说明: TCP Socket的回调函数
- * 形 参: soc TCP Socket类型
- * evt 事件类型
- * ptr 事件类型是TCP_EVT_DATA,ptr指向的缓冲区记录着接收到的TCP数据,其余事件记录IP地址
- * par 事件类型是TCP_EVT_DATA,记录接收到的数据个数,其余事件记录端口号
- * 返 回 值:
- *********************************************************************************************************
- */
- U16 tcp_callback (U8 soc, U8 evt, U8 *ptr, U16 par)
- {
- char buf[50];
- uint16_t i;
-
- /* 确保是socket_tcp的回调 */
- if (soc != socket_tcp)
- {
- return (0);
- }
-
- switch (evt)
- {
- /*
- 远程客户端连接消息
- 1、数组ptr存储远程设备的IP地址,par中存储端口号。
- 2、返回数值1允许连接,返回数值0禁止连接。
- */
- case TCP_EVT_CONREQ:
- sprintf(buf, "远程客户端请求连接IP: %d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);
- printf_debug("IP:%s port:%d\\r\\n", buf, par);
- return (1);
-
- /* 连接终止 */
- case TCP_EVT_ABORT:
- break;
-
- /* Socket远程连接已经建立 */
- case TCP_EVT_CONNECT:
- printf_debug("Socket is connected to remote peer\\r\\n");
- break;
-
- /* 连接断开 */
- case TCP_EVT_CLOSE:
- printf_debug("Connection has been closed\\r\\n");
- break;
-
- /* 发送的数据收到远程设备应答 */
- case TCP_EVT_ACK:
- break;
-
- /* 接收到TCP数据帧,ptr指向数据地址,par记录数据长度,单位字节 */
- case TCP_EVT_DATA:
- printf_debug("Data length = %d\\r\\n", par);
- for(i = 0; i < par; i++)
- {
- printf_debug("ptr[%d] = %d\\r\\n", i, ptr[i]);
- }
- break;
- }
-
- return (0);
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: TCPnetTest
- * 功能说明: TCPnet应用
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void TCPnetTest(void)
- {
- int32_t iCount;
- uint8_t *sendbuf;
- uint8_t tcp_status;
- uint16_t maxlen;
- uint8_t res;
- OS_RESULT xResult;
- const uint16_t usMaxBlockTime = 2;·
-
- /*
- 创建TCP Socket并连接,客户端连接服务器后,10秒内无数据通信将断开连接。
- 但是由于这里使能了TCP_TYPE_KEEP_ALIVE,会一直保持连接,不受10秒的时间限制。
- */
- socket_tcp = tcp_get_socket (TCP_TYPE_CLIENT | TCP_TYPE_KEEP_ALIVE, 0, 10, tcp_callback);
- if(socket_tcp != 0)
- {
- res = tcp_connect (socket_tcp, Rem_IP, PORT_NUM, LocalPort_NUM);
- printf("TCP Socket创建成功res = %d\\r\\n", res);
- }
-
- while (1)
- {
- /* RL-TCPnet处理函数 */
- main_TcpNet();
-
- /* 用于网线插拔的处理 */
- tcp_status = TCP_StatusCheck();
-
- /* 按键消息的处理 */
- if((os_evt_wait_or(0xFFFF, usMaxBlockTime) == OS_R_EVT)&&(tcp_status == __TRUE))
- {
- xResult = os_evt_get ();
- switch (xResult)
- {
- /* 接收到K1键按下,给远程TCP服务器发送8字节数据 */
- case KEY1_BIT0:
- printf_debug("tcp_get_state(socket_tcp) = %d\\r\\n", tcp_get_state(socket_tcp));
- iCount = 8;
- do
- {
- main_TcpNet();
- if (tcp_check_send (socket_tcp) == __TRUE)
- {
- maxlen = tcp_max_dsize (socket_tcp);
- iCount -= maxlen;
-
- if(iCount < 0)
- {
- /* 这么计算没问题的 */
- maxlen = iCount + maxlen;
- }
-
- sendbuf = tcp_get_buf(maxlen);
- sendbuf[0] = '1';
- sendbuf[1] = '2';
- sendbuf[2] = '3';
- sendbuf[3] = '4';
- sendbuf[4] = '5';
- sendbuf[5] = '6';
- sendbuf[6] = '7';
- sendbuf[7] = '8';
-
- /* 测试发现只能使用获取的内存 */
- tcp_send (socket_tcp, sendbuf, maxlen);
- }
-
- }while(iCount > 0);
- break;
-
- /* 其他的键值不处理 */
- default:
- break;
- }
- }
- }
- }
复制代码
14.2.4 函数tcp_max_dsize
函数原型:
- U16 tcp_max_dsize (
- U8 socket ); /* TCP socket 句柄 */ [size=3][font=新宋体] [/font][/size]
复制代码 函数描述:
函数tcp_max_dsize用于获得当前可以发送的最大报文长度(MSS,Maximum Segment Size)。在配置向导中,默认配置的MSS是1460字节,然而在实际建立连接后,此值会被动态调整,但一定是小于等于1460字节的。
(1)第1个参数是TCP Socket句柄。
(2)返回值,返回本次可以发送的最大报文长度,单位字节。
使用举例:
- /*
- *********************************************************************************************************
- * 宏定义,远程服务器的IP和端口
- *********************************************************************************************************
- */
- /* 要访问的远程服务器IP和端口配置,也就是电脑端调试助手设置的IP和端口号 */
- #define IP1 192
- #define IP2 168
- #define IP3 1
- #define IP4 2
-
- #define PORT_NUM 1001
-
- /* 这个是本地端口 */
- #define LocalPort_NUM 1024
-
- /*
- *********************************************************************************************************
- * 变量
- *********************************************************************************************************
- */
- uint8_t socket_tcp;
- uint8_t Rem_IP[4] = {IP1,IP2,IP3,IP4};
-
-
- /*
- *********************************************************************************************************
- * 函 数 名: tcp_callback
- * 功能说明: TCP Socket的回调函数
- * 形 参: soc TCP Socket类型
- * evt 事件类型
- * ptr 事件类型是TCP_EVT_DATA,ptr指向的缓冲区记录着接收到的TCP数据,其余事件记录IP地址
- * par 事件类型是TCP_EVT_DATA,记录接收到的数据个数,其余事件记录端口号
- * 返 回 值:
- *********************************************************************************************************
- */
- U16 tcp_callback (U8 soc, U8 evt, U8 *ptr, U16 par)
- {
- char buf[50];
- uint16_t i;
-
- /* 确保是socket_tcp的回调 */
- if (soc != socket_tcp)
- {
- return (0);
- }
-
- switch (evt)
- {
- /*
- 远程客户端连接消息
- 1、数组ptr存储远程设备的IP地址,par中存储端口号。
- 2、返回数值1允许连接,返回数值0禁止连接。
- */
- case TCP_EVT_CONREQ:
- sprintf(buf, "远程客户端请求连接IP: %d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);
- printf_debug("IP:%s port:%d\\r\\n", buf, par);
- return (1);
-
- /* 连接终止 */
- case TCP_EVT_ABORT:
- break;
-
- /* Socket远程连接已经建立 */
- case TCP_EVT_CONNECT:
- printf_debug("Socket is connected to remote peer\\r\\n");
- break;
-
- /* 连接断开 */
- case TCP_EVT_CLOSE:
- printf_debug("Connection has been closed\\r\\n");
- break;
-
- /* 发送的数据收到远程设备应答 */
- case TCP_EVT_ACK:
- break;
-
- /* 接收到TCP数据帧,ptr指向数据地址,par记录数据长度,单位字节 */
- case TCP_EVT_DATA:
- printf_debug("Data length = %d\\r\\n", par);
- for(i = 0; i < par; i++)
- {
- printf_debug("ptr[%d] = %d\\r\\n", i, ptr[i]);
- }
- break;
- }
-
- return (0);
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: TCPnetTest
- * 功能说明: TCPnet应用
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void TCPnetTest(void)
- {
- int32_t iCount;
- uint8_t *sendbuf;
- uint8_t tcp_status;
- uint16_t maxlen;
- uint8_t res;
- OS_RESULT xResult;
- const uint16_t usMaxBlockTime = 2;·
-
- /*
- 创建TCP Socket并连接,客户端连接服务器后,10秒内无数据通信将断开连接。
- 但是由于这里使能了TCP_TYPE_KEEP_ALIVE,会一直保持连接,不受10秒的时间限制。
- */
- socket_tcp = tcp_get_socket (TCP_TYPE_CLIENT | TCP_TYPE_KEEP_ALIVE, 0, 10, tcp_callback);
- if(socket_tcp != 0)
- {
- res = tcp_connect (socket_tcp, Rem_IP, PORT_NUM, LocalPort_NUM);
- printf("TCP Socket创建成功res = %d\\r\\n", res);
- }
-
- while (1)
- {
- /* RL-TCPnet处理函数 */
- main_TcpNet();
-
- /* 用于网线插拔的处理 */
- tcp_status = TCP_StatusCheck();
-
- /* 按键消息的处理 */
- if((os_evt_wait_or(0xFFFF, usMaxBlockTime) == OS_R_EVT)&&(tcp_status == __TRUE))
- {
- xResult = os_evt_get ();
- switch (xResult)
- {
- /* 接收到K1键按下,给远程TCP服务器发送8字节数据 */
- case KEY1_BIT0:
- printf_debug("tcp_get_state(socket_tcp) = %d\\r\\n", tcp_get_state(socket_tcp));
- iCount = 8;
- do
- {
- main_TcpNet();
- if (tcp_check_send (socket_tcp) == __TRUE)
- {
- maxlen = tcp_max_dsize (socket_tcp);
- iCount -= maxlen;
-
- if(iCount < 0)
- {
- /* 这么计算没问题的 */
- maxlen = iCount + maxlen;
- }
-
- sendbuf = tcp_get_buf(maxlen);
- sendbuf[0] = '1';
- sendbuf[1] = '2';
- sendbuf[2] = '3';
- sendbuf[3] = '4';
- sendbuf[4] = '5';
- sendbuf[5] = '6';
- sendbuf[6] = '7';
- sendbuf[7] = '8';
-
- /* 测试发现只能使用获取的内存 */
- tcp_send (socket_tcp, sendbuf, maxlen);
- }
-
- }while(iCount > 0);
- break;
-
- /* 其他的键值不处理 */
- default:
- break;
- }
- }
- }
- }
复制代码
14.2.5 函数tcp_get_buf
函数原型:
- U8* tcp_get_buf (
- U16 size ); /* 申请的缓冲区大小 */
复制代码 函数描述:
函数tcp_get_buf用于获取TCP发送缓冲区,用户将要发送的数据存到这个缓冲区中,然后通过函数tcp_send发送。发送完毕后要等待远程主机的应答,收到应答后,会在函数tcp_send中释放申请的发送缓冲区。
(1)第1个参数是要申请的缓冲区大小。
(2)返回值,返回获取的缓冲区地址。
使用这个函数要注意以下问题:
1. 每次发送都需要调用此函数获取发送缓冲区地址。
2. 申请的发送缓冲区大小不可超过最大报文长度(MSS,Maximum Segment Size),即1460字节。
3. 操作缓冲区的时候,切不可超过申请的缓冲区大小。
使用举例:
- /*
- *********************************************************************************************************
- * 宏定义,远程服务器的IP和端口
- *********************************************************************************************************
- */
- /* 要访问的远程服务器IP和端口配置,也就是电脑端调试助手设置的IP和端口号 */
- #define IP1 192
- #define IP2 168
- #define IP3 1
- #define IP4 2
-
- #define PORT_NUM 1001
-
- /* 这个是本地端口 */
- #define LocalPort_NUM 1024
-
- /*
- *********************************************************************************************************
- * 变量
- *********************************************************************************************************
- */
- uint8_t socket_tcp;
- uint8_t Rem_IP[4] = {IP1,IP2,IP3,IP4};
-
-
- /*
- *********************************************************************************************************
- * 函 数 名: tcp_callback
- * 功能说明: TCP Socket的回调函数
- * 形 参: soc TCP Socket类型
- * evt 事件类型
- * ptr 事件类型是TCP_EVT_DATA,ptr指向的缓冲区记录着接收到的TCP数据,其余事件记录IP地址
- * par 事件类型是TCP_EVT_DATA,记录接收到的数据个数,其余事件记录端口号
- * 返 回 值:
- *********************************************************************************************************
- */
- U16 tcp_callback (U8 soc, U8 evt, U8 *ptr, U16 par)
- {
- char buf[50];
- uint16_t i;
-
- /* 确保是socket_tcp的回调 */
- if (soc != socket_tcp)
- {
- return (0);
- }
-
- switch (evt)
- {
- /*
- 远程客户端连接消息
- 1、数组ptr存储远程设备的IP地址,par中存储端口号。
- 2、返回数值1允许连接,返回数值0禁止连接。
- */
- case TCP_EVT_CONREQ:
- sprintf(buf, "远程客户端请求连接IP: %d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);
- printf_debug("IP:%s port:%d\\r\\n", buf, par);
- return (1);
-
- /* 连接终止 */
- case TCP_EVT_ABORT:
- break;
-
- /* Socket远程连接已经建立 */
- case TCP_EVT_CONNECT:
- printf_debug("Socket is connected to remote peer\\r\\n");
- break;
-
- /* 连接断开 */
- case TCP_EVT_CLOSE:
- printf_debug("Connection has been closed\\r\\n");
- break;
-
- /* 发送的数据收到远程设备应答 */
- case TCP_EVT_ACK:
- break;
-
- /* 接收到TCP数据帧,ptr指向数据地址,par记录数据长度,单位字节 */
- case TCP_EVT_DATA:
- printf_debug("Data length = %d\\r\\n", par);
- for(i = 0; i < par; i++)
- {
- printf_debug("ptr[%d] = %d\\r\\n", i, ptr[i]);
- }
- break;
- }
-
- return (0);
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: TCPnetTest
- * 功能说明: TCPnet应用
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void TCPnetTest(void)
- {
- int32_t iCount;
- uint8_t *sendbuf;
- uint8_t tcp_status;
- uint16_t maxlen;
- uint8_t res;
- OS_RESULT xResult;
- const uint16_t usMaxBlockTime = 2;·
-
- /*
- 创建TCP Socket并连接,客户端连接服务器后,10秒内无数据通信将断开连接。
- 但是由于这里使能了TCP_TYPE_KEEP_ALIVE,会一直保持连接,不受10秒的时间限制。
- */
- socket_tcp = tcp_get_socket (TCP_TYPE_CLIENT | TCP_TYPE_KEEP_ALIVE, 0, 10, tcp_callback);
- if(socket_tcp != 0)
- {
- res = tcp_connect (socket_tcp, Rem_IP, PORT_NUM, LocalPort_NUM);
- printf("TCP Socket创建成功res = %d\\r\\n", res);
- }
-
- while (1)
- {
- /* RL-TCPnet处理函数 */
- main_TcpNet();
-
- /* 用于网线插拔的处理 */
- tcp_status = TCP_StatusCheck();
-
- /* 按键消息的处理 */
- if((os_evt_wait_or(0xFFFF, usMaxBlockTime) == OS_R_EVT)&&(tcp_status == __TRUE))
- {
- xResult = os_evt_get ();
- switch (xResult)
- {
- /* 接收到K1键按下,给远程TCP服务器发送8字节数据 */
- case KEY1_BIT0:
- printf_debug("tcp_get_state(socket_tcp) = %d\\r\\n", tcp_get_state(socket_tcp));
- iCount = 8;
- do
- {
- main_TcpNet();
- if (tcp_check_send (socket_tcp) == __TRUE)
- {
- maxlen = tcp_max_dsize (socket_tcp);
- iCount -= maxlen;
-
- if(iCount < 0)
- {
- /* 这么计算没问题的 */
- maxlen = iCount + maxlen;
- }
-
- sendbuf = tcp_get_buf(maxlen);
- sendbuf[0] = '1';
- sendbuf[1] = '2';
- sendbuf[2] = '3';
- sendbuf[3] = '4';
- sendbuf[4] = '5';
- sendbuf[5] = '6';
- sendbuf[6] = '7';
- sendbuf[7] = '8';
-
- /* 测试发现只能使用获取的内存 */
- tcp_send (socket_tcp, sendbuf, maxlen);
- }
-
- }while(iCount > 0);
- break;
-
- /* 其他的键值不处理 */
- default:
- break;
- }
- }
- }
- }
复制代码
14.2.6 函数tcp_send
函数原型:
- BOOL tcp_send (
- U8 socket, /* TCP socket 句柄 */
- U8* buf, /* 数据缓冲地址 */
- U16 dlen ); /* 要发送的数据个数,单位字节 */
复制代码 函数描述:
函数tcp_send用于数据包发送。
(1)第1个参数是TCP Socket句柄。
(2)第2个参数是函数tcp_get_buf获取的缓冲区地址。
(3)第3个参数是发送数据个数,单位字节。
(4)返回值,发送成功返回__TRUE,发送失败返回__FALSE。
使用这个函数要注意以下问题:
1. 不管函数tcp_send发送成功还是失败,都会释放通过函数tcp_get_buf获取的缓冲区。
2. 以下两种情况不可使用函数tcp_send发送数据包:
(1) TCP连接还未建立。
(2) 发送给远程机器的数据包还未收到应答。
3. 调用函数tcp_send前务必要调用函数tcp_get_buf获得缓冲区。
4. 申请的发送缓冲区大小不可超过最大报文长度(MSS,Maximum Segment Size),即1460字节。
5. 操作缓冲区的时候,切不可超过申请的缓冲区大小。
使用举例:- /*
- *********************************************************************************************************
- * 宏定义,远程服务器的IP和端口
- *********************************************************************************************************
- */
- /* 要访问的远程服务器IP和端口配置,也就是电脑端调试助手设置的IP和端口号 */
- #define IP1 192
- #define IP2 168
- #define IP3 1
- #define IP4 2
-
- #define PORT_NUM 1001
-
- /* 这个是本地端口 */
- #define LocalPort_NUM 1024
-
- /*
- *********************************************************************************************************
- * 变量
- *********************************************************************************************************
- */
- uint8_t socket_tcp;
- uint8_t Rem_IP[4] = {IP1,IP2,IP3,IP4};
-
-
- /*
- *********************************************************************************************************
- * 函 数 名: tcp_callback
- * 功能说明: TCP Socket的回调函数
- * 形 参: soc TCP Socket类型
- * evt 事件类型
- * ptr 事件类型是TCP_EVT_DATA,ptr指向的缓冲区记录着接收到的TCP数据,其余事件记录IP地址
- * par 事件类型是TCP_EVT_DATA,记录接收到的数据个数,其余事件记录端口号
- * 返 回 值:
- *********************************************************************************************************
- */
- U16 tcp_callback (U8 soc, U8 evt, U8 *ptr, U16 par)
- {
- char buf[50];
- uint16_t i;
-
- /* 确保是socket_tcp的回调 */
- if (soc != socket_tcp)
- {
- return (0);
- }
-
- switch (evt)
- {
- /*
- 远程客户端连接消息
- 1、数组ptr存储远程设备的IP地址,par中存储端口号。
- 2、返回数值1允许连接,返回数值0禁止连接。
- */
- case TCP_EVT_CONREQ:
- sprintf(buf, "远程客户端请求连接IP: %d.%d.%d.%d", ptr[0], ptr[1], ptr[2], ptr[3]);
- printf_debug("IP:%s port:%d\\r\\n", buf, par);
- return (1);
-
- /* 连接终止 */
- case TCP_EVT_ABORT:
- break;
-
- /* Socket远程连接已经建立 */
- case TCP_EVT_CONNECT:
- printf_debug("Socket is connected to remote peer\\r\\n");
- break;
-
- /* 连接断开 */
- case TCP_EVT_CLOSE:
- printf_debug("Connection has been closed\\r\\n");
- break;
-
- /* 发送的数据收到远程设备应答 */
- case TCP_EVT_ACK:
- break;
-
- /* 接收到TCP数据帧,ptr指向数据地址,par记录数据长度,单位字节 */
- case TCP_EVT_DATA:
- printf_debug("Data length = %d\\r\\n", par);
- for(i = 0; i < par; i++)
- {
- printf_debug("ptr[%d] = %d\\r\\n", i, ptr[i]);
- }
- break;
- }
-
- return (0);
- }
-
- /*
- *********************************************************************************************************
- * 函 数 名: TCPnetTest
- * 功能说明: TCPnet应用
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void TCPnetTest(void)
- {
- int32_t iCount;
- uint8_t *sendbuf;
- uint8_t tcp_status;
- uint16_t maxlen;
- uint8_t res;
- OS_RESULT xResult;
- const uint16_t usMaxBlockTime = 2;·
-
- /*
- 创建TCP Socket并连接,客户端连接服务器后,10秒内无数据通信将断开连接。
- 但是由于这里使能了TCP_TYPE_KEEP_ALIVE,会一直保持连接,不受10秒的时间限制。
- */
- socket_tcp = tcp_get_socket (TCP_TYPE_CLIENT | TCP_TYPE_KEEP_ALIVE, 0, 10, tcp_callback);
- if(socket_tcp != 0)
- {
- res = tcp_connect (socket_tcp, Rem_IP, PORT_NUM, LocalPort_NUM);
- printf("TCP Socket创建成功res = %d\\r\\n", res);
- }
-
- while (1)
- {
- /* RL-TCPnet处理函数 */
- main_TcpNet();
-
- /* 用于网线插拔的处理 */
- tcp_status = TCP_StatusCheck();
-
- /* 按键消息的处理 */
- if((os_evt_wait_or(0xFFFF, usMaxBlockTime) == OS_R_EVT)&&(tcp_status == __TRUE))
- {
- xResult = os_evt_get ();
- switch (xResult)
- {
- /* 接收到K1键按下,给远程TCP服务器发送8字节数据 */
- case KEY1_BIT0:
- printf_debug("tcp_get_state(socket_tcp) = %d\\r\\n", tcp_get_state(socket_tcp));
- iCount = 8;
- do
- {
- main_TcpNet();
- if (tcp_check_send (socket_tcp) == __TRUE)
- {
- maxlen = tcp_max_dsize (socket_tcp);
- iCount -= maxlen;
-
- if(iCount < 0)
- {
- /* 这么计算没问题的 */
- maxlen = iCount + maxlen;
- }
-
- sendbuf = tcp_get_buf(maxlen);
- sendbuf[0] = '1';
- sendbuf[1] = '2';
- sendbuf[2] = '3';
- sendbuf[3] = '4';
- sendbuf[4] = '5';
- sendbuf[5] = '6';
- sendbuf[6] = '7';
- sendbuf[7] = '8';
-
- /* 测试发现只能使用获取的内存 */
- tcp_send (socket_tcp, sendbuf, maxlen);
- }
-
- }while(iCount > 0);
- break;
-
- /* 其他的键值不处理 */
- default:
- break;
- }
- }
- }
- }
复制代码 |
|