8.1. SOCKETS
8.1.1. 概述
LWIP协议栈中SOCKET用法
8.1.2. DEMO工程
apps/demo/demo_DevkitBoard
8.1.3. TCP Client
示例说明
通过创建tcp socket连接到指定ip和端口号的服务端。当成功建立连接后,应用程序会向服务端发送ASCII数据, 并等待服务端回复,当客户端成功接收到服务端的数据后,会向服务端发送接收数据成功的信息。
TCP客户端创建步骤
1.创建socket
void *fd = NULL; fd = sock_reg(AF_INET, SOCK_STREAM, 0, NULL, NULL); if(NULL == fd) { printf("sock_reg fail\n"); }
2.设置socket属性(可选)
//如: unsigned int opt = 1; if(sock_setsockopt(fd, IPPROTO_TCP, TCP_QUICKACK, &opt, sizeof(opt)) < 0) { printf("sock_setsockopt fail\n"); }
3.绑定IP地址、端口号等信息(可选)
struct sockaddr_in local_addr; local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = htonl(INADDR_ANY) local_addr.sin_port = htons(32768); if (sock_bind(fd, (struct sockaddr *)&local_addr), sizeof(local_addr)) { printf("sock_bind fail\n"); }
4.设置连接方IP和端口号, 并连接。
struct sockaddr_in dest_addr; dest_addr.sin_family = AF_INET; dest_addr.sin_addr.s_addr = inet_addr("192.168.1.1") dest_addr.sin_port = htons(32769); if(sock_connect(fd, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in))) { printf("sock_connect fail\n"); }
5.接收数据
char buf[1024] = {0}; int recv_len = sock_recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL); if(recv_len > 0) { printf("received %d Bytes, data : %s\n", recv_len, buf); }
6.发送数据
char *send_buf = "123456"; int send_len = sock_send(fd, send_buf, strlen(send_buf), 0);
7.关闭socket
if(fd) { sock_unreg(fd); fd = NULL; }
示例
示例代码见 apps\common\example\network_protocols\sockets\tcp\client\main.c
, 测试时需要在 apps/demo/demo_DevKitBoard/include/demo_config.h
,开启宏 USE_TCP_CLIENT_TEST
。
操作说明
示例需要运行在STA模式 (注:如何进行sta和ap切换,请参考 Wi-Fi部分 )
借助tcq助手创建指定ip和端口号的服务端,并保证tcp助手和客户端处于同一网段下
编译工程,烧录镜像,复位启动
系统启动并成功联网后,tcp助手会接收到客户端的ASCII数据,同时可以通过tcp助手向客户端发送数据,数据发送成功后可以通过串口软件看到服务端发送回来的数据
示例流程:
c_main()
入口创建任务
tcp_client_start
tcp_client_start
函数流程通过
wifi_get_sta_connect_state
函数检测是否通过dhcp成功获取到ip成功通过dhcp获取到ip后,启动
tcp_client_task
任务,退出tcp_client_start
tcp_client_task
任务流程通过
tcp_client_init
进行TCP Client初始化,包括:创建socket,连接到服务端通过
tcp_send_data
向服务端发送数据通过
tcp_recv_data
接收服务端数据
8.1.4. TCP Server
示例说明
通过创建TCP socket并绑定指定端口后开启监听,等待客户端连接。当接收到客户端连接请求并成功建立连接后, 应用程序会等待接收客户端的数据,当服务端成功接收到客户端的数据后,会向对应客户端发送接收数据成功的信息。
TCP服务端创建步骤
1.创建socket
void *fd = NULL; fd = sock_reg(AF_INET, SOCK_STREAM, 0, NULL, NULL); if(NULL == fd) { printf("sock_reg fail\n"); }
2.设置socket属性(可选)
//如: unsigned int opt = 1; if(sock_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR ,&opt, sizeof(opt)) < 0) { printf("sock_setsockopt fail\n"); }
3.绑定IP地址、端口号等信息(可选)
struct sockaddr_in local_addr; local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = htonl(INADDR_ANY) local_addr.sin_port = htons(32768); if (sock_bind(fd, (struct sockaddr *)&local_addr), sizeof(local_addr)) { printf("sock_bind fail\n"); }
4.开启监听
if (sock_listen(fd, 3)) { printf("sock_listen fail\n"); }
5.等待客户端连接
void *c_fd = NULL; int flag = 1; struct sockaddr_in c_addr; socklen_t len = sizeof(struct sockaddr_in); c_fd = sock_accept(fd, (struct sockaddr*)&c_addr, &len, NULL, NULL); flag = 0; if(c_fd == NULL) { printf("sock_accept fail\n"); }
6.接收数据
char buf[1024] = {0}; int recv_len = sock_recv(fd, buf, sizeof(buf), 0); if(recv_len > 0) { printf("received %d Bytes, data : %s\n", recv_len, buf); }
7.发送数据
char *send_buf = "123456"; int send_len = sock_send(fd, send_buf, strlen(send_buf), 0);
8.关闭socket
if(fd) { flag = 1; sock_set_quit(fd); while(flag) //等待sock_accept退出后再释放socket,防止释放socket后还在使用。 { os_time_dly(20); } sock_unreg(fd); fd = NULL; }
示例
示例代码见 apps\common\example\network_protocols\sockets\tcp\server\main.c
, 测试时需要在 apps/demo/demo_DevKitBoard/include/demo_config.h
,开启宏 USE_TCP_SERVER_TEST
。
操作说明
系统启动并成功联网后,借助tcq助手创建客户端,设置好服务端ip和端口号后发起连接,成功连接后可以通过串口软件看到提示信息, 此时客户端可以向服务端发送一些数据,当服务端成功接收到数据后,会向对应客户端发送接收数据成功的信息。
注意:本例程暂时只提供了STA模式下的TCP Server。AP模式下的TCP Server需要自行编写。
示例流程如下:
c_main()
入口创建
tcp_server_start
任务
tcp_server_start
函数流程调用
tcp_server_init
进行初始化,退出tcp_server_start
tcp_server_init
任务流程创建TCP socket。
创建接收客户端连接请求任务
tcp_sock_accpet
创建接收客户端数据任务
tcp_recv_handler
tcp_sock_accpet
函数流程等待客户端连接,成功接收到客户端请求后,会把对应客户端的信息保存到链表中
tcp_recv_handler
函数流程接收客户端数据,成功接收到数据后,向对应客户端发送接收数据成功的信息
调用
tcp_server_exit
可关闭网路连接,需要使用者自行调用
8.1.5. UDP Client
示例说明
UDP通信无需建立连接关系,创建套接字后便可以向指定服务端发送数据,示例请参考UDP Server
UDP客户端创建步骤
1.创建socket
void *fd = NULL; fd = sock_reg(AF_INET, SOCK_DGRAM, 0, NULL, NULL); if(NULL == fd) { printf("sock_reg fail\n"); }
2.设置socket属性(可选)
//如: unsigned int millsec = 100; if(ock_setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (const void *)&millsec, sizeof(millsec)) < 0) { printf("sock_setsockopt fail\n"); }
3.绑定IP地址、端口号等信息(可选)
struct sockaddr_in c_addr; c_addr.sin_family = AF_INET; c_addr.sin_addr.s_addr = htonl(INADDR_ANY) c_addr.sin_port = htons(32768); if (sock_bind(fd, (struct sockaddr *)&c_addr), sizeof(c_addr)) { printf("sock_bind fail\n"); }
4.接收数据
int recv_len; char recv_buf[1024]; struct sockaddr_in s_addr = {0}; socklen_t len = sizeof(s_addr); for(;;) { recv_len = sock_recvfrom(fd, recv_buf, sizeof(recv_buf), 0, \ (struct sockaddr *)&s_addr, &len); if(recv_len > 0) { printf("received %d Bytes, data : %s\n", recv_len, recv_buf); } }
5.发送数据
int send_len = sock_sendto(fd, send_buf, strlen(send_buf), 0, \ (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));
6.关闭socket
if(fd) { sock_unreg(fd); fd = NULL; }
8.1.6. UDP Server
示例说明
通过创建的udp socket并绑定指定ip和端口号后,等待接收客户端数据,当成功接收到数据后,再重新把接收到的数据发送回客户端。
UDP服务端创建步骤
1.创建socket
void *fd = NULL; fd = sock_reg(AF_INET, SOCK_DGRAM, 0, NULL, NULL); if(NULL == fd) { printf("sock_reg fail\n"); }
2.设置socket属性(可选)
//如: unsigned int opt = 1; if(sock_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR ,&opt, sizeof(opt)) < 0) { printf("sock_setsockopt fail\n"); }
3.绑定IP地址、端口号等信息
struct sockaddr_in s_addr; s_addr.sin_family = AF_INET; s_addr.sin_addr.s_addr = htonl(INADDR_ANY) s_addr.sin_port = htons(32768); if (sock_bind(fd, (struct sockaddr *)&s_addr), sizeof(s_addr)) { printf("sock_bind fail\n"); }
4.接收数据
int recv_len; char recv_buf[1024]; struct sockaddr_in c_addr = {0}; socklen_t len = sizeof(c_addr); for(;;) { recv_len = sock_recvfrom(fd, recv_buf, sizeof(recv_buf), 0, \ (struct sockaddr *)&c_addr, &len); if(recv_len > 0) { printf("received %d Bytes, data : %s\n", recv_len, recv_buf); } }
5.发送数据
int send_len = sock_sendto(fd, send_buf, strlen(send_buf), 0, \ (struct sockaddr *)&c_addr, sizeof(struct sockaddr_in));
6.关闭socket
if(fd) { sock_unreg(fd); fd = NULL; }
操作说明
示例需要运行在STA模式 (注:如何进行sta和ap切换,请参考 Wi-Fi部分 )
编译工程,烧录镜像,复位启动。
系统启动并成功联网后,借助tcp/udp助手向指定ip和端口号的UDP服务端发送数据,通过串口软件可以看到tcp/udp助手发送过来的数据,同时tcp/udp助手也会接收到客户端返回的同样的数据。
示例
示例代码见 apps\common\example\network_protocols\sockets\udp\server\main.c
, 测试时需要在 apps/demo/demo_DevKitBoard/include/demo_config.h
,开启宏 USE_UDP_SERVER_TEST
。
示例流程如下:
c_main()
入口创建
udp_server_start
任务
udp_server_start
函数流程通过
wifi_get_sta_connect_state
函数检测是否通过dhcp成功获取到ip成功通过dhcp获取到ip后,调用
udp_server_init
进行初始化,退出udp_server_start
udp_server_init
函数流程A)创建UDP socket,绑定ip和端口号 B) 创建接收客户端数据任务
udp_recv_handler
udp_recv_handler
函数流程等待接收客户端数据,成功接收到数据后再重新把同样的数据发回给客户端
调用
udp_server_exit
可关闭连接