外话:各位手头上没有esp8266的开发板注意了,目前开发快正在进行“免费开发板活动”,本人就是在他们那里申请到的开发板,开发快提供的不单单是开发板,还有他们强大的云端服务功能,实现了微信、云平台等物联网所需要的所有功能,其功能齐全,代码简洁,对于想用wifi作为产品和互联网沟通的桥梁的我们来说,确实是一个很好的选择,另外他们还有其他的模块,比如2G通信和GPS。目前论坛活动地址:http://bbs.kaifakuai.com/forum.php?mod=viewthread&tid=981&extra=page%3D1,开发快官网地址:http://www.kaifakuai.com/ 》》》》》》写于2017年1月12日
这里将用小E开发板实现UDP、TCP CLIENT、TCP SERVICE传输,并不涉及程序的编译下载过程,想知道这些内容请参考前文:http://blog.csdn.net/chengdong1314/article/details/53913212
UDP传输
在开发快给的原始程序中只是有关于与微信云平台的程序,对于局域网内用网络调试串口的程序并没有,现在我想先调试一下播放器的功能,所以这里没有在原来的程序加上UDP传输的功能,具体实现如下:
在代码上首先创建一个新的任务:
void et_user_main(void *pvParameters)
{
.........................................
xTaskCreate(our_main, "our_main", 1024, NULL, 2, NULL);
error:
vTaskDelete(NULL);
return ;
}
然后在our_main任务中使用socket编程实现udp数据传输,该任务的源代码如下:
void our_main(void *pvParameters){
LOCAL int32 sock_fd;
struct sockaddr_in server_addr;
struct sockaddr_in from;
int nNetTimeout = 1000;
int ret,fromlen;
char udp_msg[UDP_DATA_LEN];
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(UDP_LOCAL_PORT);
server_addr.sin_len = sizeof(server_addr);
do{
sock_fd = socket(AF_INET, SOCK_DGRAM, 0); //创建socket
if (sock_fd == -1) {
os_printf("ESP8266 UDP task > failed to create sock!\n");
vTaskDelay(1000/portTICK_RATE_MS);
}
}while(sock_fd == -1);
os_printf("ESP8266 UDP task > socket OK!\n");
do{
ret = bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)); //绑定
if (ret != 0) {
os_printf("ESP8266 UDP task > captdns_task failed to bind sock!\n");
vTaskDelay(1000/portTICK_RATE_MS);
}
}while(ret != 0);
os_printf("ESP8266 UDP task > bind OK!\n");
while(1){
memset(udp_msg, 0, UDP_DATA_LEN);
memset(&from, 0, sizeof(from));
setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&nNetTimeout,sizeof(int)); //设置socket超时
fromlen = sizeof(struct sockaddr_in);
ret = recvfrom(sock_fd, (uint8 *)udp_msg, UDP_DATA_LEN, 0,(struct sockaddr*)&from,(socklen_t *)&fromlen); //读取数据
if (ret > 0) {
os_printf("ESP8266 UDP task > recv %d Bytes from Port %d %s\n",ret,ntohs(from.sin_port), inet_ntoa(from.sin_addr)); //接收到数据
sendto(sock_fd,(uint8*)udp_msg, ret, 0, (struct sockaddr *)&from,fromlen); //把源数据传回去
}
}
}
上面就是socket建立udp传输的所有过程,其中的宏定义如下:
#define UDP_LOCAL_PORT 1200
#define UDP_DATA_LEN 255
编译下载运行之后我们在串口和网络调试助手中看到下面的打印内容:
到了这里UDP算是OK了
UDP数据传输的源代码:http://download.csdn.net/detail/chengdong1314/9726724
TCP CLIENT传输
这里和UDP传输一样建立一个任务:xTaskCreate(our_main, "our_main", 1024, NULL, 2, NULL);
然后在our_main任务中创建socket并且初始化接口,实现tcp client,这里的代码为:
void our_main(void *pvParameters){
key_gpio_t key;
struct sockaddr_in remote_ip;
int recbytes;
do{
sta_socket = socket(AF_INET, SOCK_STREAM, 0); //创建socket
if (sta_socket == -1) {
os_printf("ESP8266 TCP client task > failed to create sock!\n");
vTaskDelay(1000/portTICK_RATE_MS);
}
}while(sta_socket == -1);
os_printf("ESP8266 TCP client task > socket OK!\n");
bzero(&remote_ip, sizeof(struct sockaddr_in));
remote_ip.sin_family = AF_INET;
remote_ip.sin_addr.s_addr = inet_addr(SERVER_IP);
remote_ip.sin_port = htons(SERVER_PORT);
while (0 != connect(sta_socket, (struct sockaddr *)(&remote_ip), sizeof(struct sockaddr))) {
close(sta_socket);
vTaskDelay(1000 / portTICK_RATE_MS);
os_printf("ESP8266 TCP client task > connect fail!\n");
continue;
}
os_printf("ESP8266 TCP client task > connect ok!\n");
gpio16_input_conf();
xTaskCreate(user_key_poll_task, "tcpsend_task", 512, NULL, 2, NULL);
while(1){
char *recv_buf = (char *)zalloc(128);
while ((recbytes = read(sta_socket , recv_buf, 128)) > 0) {
char *pbuf = (char *)zalloc(128);
recv_buf[recbytes] = 0;
os_printf("ESP8266 TCP client task > recv data %d bytes!\nESP8266 TCPclient task > %s\n", recbytes, recv_buf);
}
free(recv_buf);
if (recbytes <= 0) {
close(sta_socket);
os_printf("ESP8266 TCP client task > read data fail!\n");
}
}
}
当连接成功之后这里配置user按键任务,该按键任务去判断gpio16上面的user按键是否被按下,当被按下的时候将调用发送命令发送递加的ascii码,该任务如下:
void user_key_poll_task(void *pvParameters){
et_uint32 value,t;
u8 pbuf[32];
for(t=0;t<32;t++)
{
pbuf[t]=' '+t;
}
while(1)
{
value = gpio16_input_get();
if(!value)
{
delay_ms(20);
value = gpio16_input_get();
if(!value)
{
os_printf("begin to send msg\n");
if (write(sta_socket, pbuf, strlen(pbuf) + 1) < 0){
close(sta_socket);
vTaskDelay(1000 / portTICK_RATE_MS);
os_printf("ESP8266 TCP client task > send fail\n");
continue;
}
for(t=0;t<32;t++)
{
pbuf[t] +=1 ;
if(pbuf[t]>'~') pbuf[t]=' ';
}
os_printf("ESP8266 TCP client task > send success\n");
delay_ms(5000);
}
}
}
os_printf("end userkey\n");
vTaskDelete(NULL);
}
该程序测试OK,实验现象如下:
TCP CLIENT数据传输的源代码:http://download.csdn.net/detail/chengdong1314/9728148
TCP SERVICE传输
这里的处理方式和tcp client传输一样建立our_main任务,该任务具体如下:
void our_main(void *pvParameters){
int32 listenfd;
int32 ret;
int32 len;
int recbytes;
struct sockaddr_in server_addr,remote_addr;
int stack_counter=0;
char *recv_buf;
/* Construct local address structure */
memset(&server_addr, 0, sizeof(server_addr)); /* Zero out structure */
server_addr.sin_family = AF_INET; /* Internet address family */
server_addr.sin_addr.s_addr = INADDR_ANY; /* Any incoming interface */
server_addr.sin_len = sizeof(server_addr);
server_addr.sin_port = htons(SERVER_PORT); /* Local port */
/* Create socket for incoming connections */
do{
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1) {
printf("ESP8266 TCP server task > socket error\n");
vTaskDelay(1000/portTICK_RATE_MS);
}
}while(listenfd == -1);
printf("ESP8266 TCP server task > create socket OK\n");
/* Bind to the local port */
do{
ret = bind(listenfd, (struct sockaddr *)&server_addr,sizeof(server_addr));
if (ret != 0) {
printf("ESP8266 TCP server task > bind fail\n");
vTaskDelay(1000/portTICK_RATE_MS);
}
}while(ret != 0);
printf("ESP8266 TCP server task > port:%d\n",ntohs(server_addr.sin_port));
do{
/* Listen to the local connection */
ret = listen(listenfd, MAX_CONN);
if (ret != 0) {
printf("ESP8266 TCP server task > failed to set listen queue!\n");
vTaskDelay(1000/portTICK_RATE_MS);
}
}while(ret != 0);
printf("ESP8266 TCP server task > listen ok\n");
gpio16_input_conf();
xTaskCreate(user_key_poll_task, "tcpsend_task", 512, NULL, 2, NULL);
len = sizeof(struct sockaddr_in);
for (;;) {
printf("ESP8266 TCP server task > wait client\n");
/*block here waiting remote connect request*/
if ((client_sock = accept(listenfd, (struct sockaddr *)&remote_addr,(socklen_t *)&len)) < 0) {
printf("ESP8266 TCP server task > accept fail\n");
continue;
}
printf("ESP8266 TCP server task > Client from %s %d\n",
inet_ntoa(remote_addr.sin_addr), htons(remote_addr.sin_port));
recv_buf = (char *)zalloc(128);
while ((recbytes = read(client_sock , recv_buf, 128)) > 0) {
recv_buf[recbytes] = 0;
printf("ESP8266 TCP server task > read data success %d!\nESP8266 TCPserver task > %s\n", recbytes, recv_buf);
}
free(recv_buf);
if (recbytes <= 0) {
printf("ESP8266 TCP server task > read data fail!\n");
close(client_sock);
}
}
}
这里开始监听端口后将创建一个按键任务user_key_poll_task来判断user按键的状态,如果按下了该按键将会发送信息,该任务代码如下:
void user_key_poll_task(void *pvParameters){
et_uint32 value,t;
u8 pbuf[32];
for(t=0;t<32;t++)
{
pbuf[t]=' '+t;
}
while(1)
{
value = gpio16_input_get();
if(!value)
{
delay_ms(20);
value = gpio16_input_get();
if(!value)
{
os_printf("begin to send msg\n");
if (write(client_sock, pbuf, strlen(pbuf) + 1) < 0){
close(client_sock);
vTaskDelay(1000 / portTICK_RATE_MS);
os_printf("ESP8266 TCP client task > send fail\n");
continue;
}
for(t=0;t<32;t++)
{
pbuf[t] +=1 ;
if(pbuf[t]>'~') pbuf[t]=' ';
}
os_printf("ESP8266 TCP SERVICE task > send success\n");
delay_ms(5000);
}
}
}
os_printf("end userkey\n");
vTaskDelete(NULL);
}
实验现象如下:
TCP service数据传输的源代码:http://download.csdn.net/detail/chengdong1314/9729105
这里上传上网络调试调试工具:http://download.csdn.net/detail/chengdong1314/9723958
UDP数据传输的源代码:http://download.csdn.net/detail/chengdong1314/9726724
TCP CLIENT数据传输的源代码:http://download.csdn.net/detail/chengdong1314/9728148
TCP service数据传输的源代码:http://download.csdn.net/detail/chengdong1314/9729105
我编写出这个程序的文档:http://download.csdn.net/detail/chengdong1314/9724938
借鉴的文章(这篇文章帮我很多忙):http://www.cnblogs.com/magicbox/archive/2012/02/15/2363875.html
还有开发快提供的文档:
《小E文档.zip》这里包括了开发快公司对小e做的优化手册,比如flash函数的说明等等,其中我参考了《20A-ESP8266__RTOS_SDK__Programming Guide__CN_v1.0.5.pdf》(这里有一些小错误):http://download.csdn.net/detail/chengdong1314/9724938