实验环境:
1. 虚拟机:VirtualBox6.0
2. Ubuntu系统: ubuntu-20.04.1-desktop-amd64
3. ESP8266: NodeMCU开发板
4. SDK:V3.4
5. 使用乐鑫SDK提供examples实验使用
@0、补充:编译完成后下载出现ttyUSB0找不到的问题:
(图0.00找不到ttyUSB0)
这样需要设置好虚拟机和Ubuntu,然后插拔USB重新挂载:
(图0.10Ubuntu设置USB)
(图0.11拔插USB显示连接上USB)
最后使用命令使Ubuntu挂载USB0:
1.sudo usermod -a -G dialout $USER
2.sudo chmod -R 777 /dev/ttyUSB0
(图0.12可以正常下载和窗口监视)
=================================== 分割线 ====================================
@1、Socket预备知识:
https://blog.csdn.net/pashanhu6402/article/details/96428887
(图1.00Socket在网络中的结构)
@2、TcpServer和 TcpClient
(图2.00TCP协议结构流程图)
TcpServer和 TcpClient流程基本相同,不过TcpServer相对来说多了些流程。复制到工作目录下边。
(图2.10复制Tcp_Server文件到实验目录)
打开Tcp_Server.c文件修改app_main为TcpServer_init,使用CONFIG_EXAMPLE_IPV4而非IPV6。
(图2.11修改app_main方便调用)
(图2.11修改app_main方便调用1)
(图2.12设置端口且使用IPV4)
在app_main函数中调用TcpServer_init完成TcpServer功能
(图2.13调用TcpServer功能)
下载即可使用
@2、tcpclient功能设置与tcpserver基本相同!
@3、udpclient功能设置和udpserver操作也基本相同!!!
for(;;)
{
//使用IPV4
struct sockaddr_in destAddr; //处理网络通信地址的结构体(服务器)
destAddr.sin_addr.s_addr = htonl(INADDR_ANY); //把本机字节顺序转化为网络字节顺序
destAddr.sin_family = AF_INET; //domain:(TCP/IP – IPv4)
destAddr.sin_port = htons(PORT); //将主机字节顺序转换为网络字节顺序
addr_family = AF_INET; //domain:(TCP/IP – IPv4)
ip_protocol = IPPROTO_IP; //#define IPPROTO_IP 0 /* dummy for IP */
inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1); //转换IP地址到ASIIC字符串的函数
//===================================================================
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol); //返回状态码
//ESP_LOGI == printf
if (listen_sock < 0) { //返回-1表示失败,其他值参考:https://blog.csdn.net/sstnba/article/details/83380656
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket created"); //返回正常值说明Socket已经建立起来了
int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr)); //把一个本地协议地址赋予一个套接字
//返回值表示绑定操作是否成功,0表示成功, -1表示不成功。函数的返回值千万不要忽视,上次就被人说了。
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket binded");
err = listen(listen_sock, 1); //设置监听和队列数
if (err != 0) {
ESP_LOGE(TAG, "Error occured during listen: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket listening"); //成功监听
//===================================================================
//使用IPV4
struct sockaddr_in sourceAddr; //处理网络通信地址的结构体(客户端)
uint addrLen = sizeof(sourceAddr); //地址大小
int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
break;
}
ESP_LOGI(TAG, "Socket accepted"); //阻塞处理-进行握手连接
//===================================================================
while (1) //处于监听状态
{
int len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0); //从TCP连接的另一端接收数据
// Error occured during receiving
if (len < 0){ //recv在copy时出错了
ESP_LOGE(TAG, "recv failed: errno %d", errno);
break;
}
// Connection closed
else if (len == 0) { //等待协议接收数据时网络中断了
ESP_LOGI(TAG, "Connection closed");
break;
}
// Data received
else { //返回值>0,接收实际copy字节数
inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
ESP_LOGI(TAG, "%s", rx_buffer);
int err = send(sock, rx_buffer, len, 0); //发送回所接收到的数据
if (err < 0) {
ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
break;
}
}
}
if (sock != -1) {
ESP_LOGE(TAG, "Shutting down socket and restarting...");
shutdown(sock, 0);
close(sock);
}
}
技术总结:
@一、注意USB0的挂载问题!
@二、要复制components文件到实验目录,否则会找不到protocol_examples_common.h头文件!
(图3.13网络连接头文件)