一起学习CC3200系列教程之2个TCP_非阻塞及阻塞设置
来源:互联网 发布:ubuntu 网络文件夹 编辑:程序博客网 时间:2024/05/16 15:08
一起学习CC3200系列教程之2个TCP_非阻塞及阻塞设置
阿汤哥
序:
能力有限,难免有错,有问题请联系我,
QQ1519256298 hytga@163.com
Pdf下载http://pan.baidu.com/s/1hqiWB56
关键字:socket ,阻塞,非阻塞,SetSockOpt
现在我们介绍如果创建一个TCP连接。
开发环境:
CCS,sdk1.1,freertos,
软件流程:
我们创建两个任务,第一个任务比第二个任务多了一个网络设置的功能,其他的一致,我们就用第一个任务来表达,任务初始化CC3200为STA模式,并连上AP,创建一个socket,读取远端的数据,并把读到的数据原封不动地发送回去。自动检测socket连接有没有断开,并自动重新连接,没有做网络断开连接的检测。
这里我们用了两种方式:阻塞及非阻塞
阻塞:
任务会阻塞在写和读的函数上,直到发送出去,读函数会直接返回,所以在返回值做了一个判断:有没有断开连接,有就重连。当阻塞某一函数时,任务会自动切换。因此不用我们去延迟任务
非阻塞:
任务不会阻塞在读的函数上,写函数有没有阻塞我没测过,估计得用测量这个函数的执行时间才能知道有没有阻塞,挺麻烦的,所以略过。当socket断开连接会导致发送错误,利用这个特性,在发送错误时我们进行重连,因此这个会导致无用的信息传输浪费了电量,而且响应不及时,改进方法:用select,这个改天说。任务不会自动切换,需要我们去延迟任务,切换任务,这里我是使用的是用SetSockOpt来设置非阻塞的
main函数
//****************************************************************************// MAIN FUNCTION//****************************************************************************void main(){ long lRetVal = -1; //Board Initialization BoardInit(); // // 初始化串口 // PinMuxConfig(); //UART Initialization MAP_PRCMPeripheralReset(PRCM_UARTA0); MAP_UARTConfigSetExpClk(CONSOLE,MAP_PRCMPeripheralClockGet(CONSOLE_PERIPH), UART_BAUD_RATE,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); //Display Application Banner on UART Terminal DisplayBanner(APPLICATION_NAME); // // Simplelinkspawntask // lRetVal = VStartSimpleLinkSpawnTask(SPAWN_TASK_PRIORITY); if(lRetVal < 0) { UART_PRINT("Unable to start simpelink spawn task\n\r"); LOOP_FOREVER(); } //创建任务1 lRetVal = osi_TaskCreate(TcpEchoClient, (signed char*)"TcpEchoClient", TcpEchoClient_STACK_SIZE, NULL, TcpEchoClient_PRIORITY, NULL ); if(lRetVal < 0) { UART_PRINT("Unable to create task\n\r"); LOOP_FOREVER(); } //创建任务2,这个任务必须是比第一个任务的优先级低,因为第一个任务有一个初始化网络的设置 // lRetVal = osi_TaskCreate(TcpEchoClient2, (signed char*)"TcpEchoClient2", TcpEchoClient_STACK_SIZE, NULL, TcpEchoClient_PRIORITY - 1, NULL ); if(lRetVal < 0) { UART_PRINT("Unable to create task\n\r"); LOOP_FOREVER(); } // // 开始任务调度 // osi_start(); while (1) { }}
任务1,2,网络设置
//本函数是参考sdk1.1.0的network_if的函数的static void WlanInit(void) { long lRetVal = -1; // // 复位设备的wlan状态 // Network_IF_ResetMCUStateMachine(); // // 把设备设置成sta模式 // lRetVal = Network_IF_InitDriver(ROLE_STA); if(lRetVal < 0) { UART_PRINT("Failed to start SimpleLink Device\n\r",lRetVal); LOOP_FOREVER(); } //网络参数 SecurityParams.Key = (signed char *)SECURITY_KEY; SecurityParams.KeyLen = strlen(SECURITY_KEY); SecurityParams.Type = SECURITY_TYPE; // // 连接AP // lRetVal = Network_IF_ConnectAP(SSID_NAME, SecurityParams); if(lRetVal < 0) { UART_PRINT("Connection to an AP failed\n\r"); LOOP_FOREVER(); }}void TcpEchoClient(void *pvParameters){<span style="white-space:pre"></span>//任务1 SlSockAddrIn_t sAddr; SlSockNonblocking_t enableOption; SlSockKeepalive_t xKeepaliveEnableOption; unsigned int ulDestiantionIP; char szRevBuf[100]; int iRevLen,iAddrSize,iStatus; int iHeartBeatCounter = 0; //设置网络, //为什么需要这里设置? //因为本网络设置需要启动任务调度器:这个任务需要调度器去调度VStartSimpleLinkSpawnTask这个任务 //如果没有启动调度器,会导致wlan连不上。 WlanInit(); //设置服务器端的ip及端口信息 sAddr.sin_family = SL_AF_INET; sAddr.sin_port = sl_Htons((unsigned short)9000); //把“192.168.3.27”转成一个没有符号的32整数 siIp_StrToInt("192.168.3.27",&ulDestiantionIP); sAddr.sin_addr.s_addr = sl_Htonl((unsigned int)ulDestiantionIP); iAddrSize = sizeof(SlSockAddrIn_t); UART_PRINT("\r\nTcpEchoClient1\r\n"); while(1) { //g_iEchoSocketID 等于0.表示这个socket是没有连接上的 if (g_iEchoSocketID == 0) { //创建一个socket g_iEchoSocketID = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); if( g_iEchoSocketID < 0 ) { //出错处理:略 } // 连接到服务器 iStatus = sl_Connect(g_iEchoSocketID, ( SlSockAddr_t *)&sAddr, iAddrSize); if( iStatus < 0 ) { // error sl_Close(g_iEchoSocketID); g_iEchoSocketID = 0; }else { UART_PRINT("\r\n1:Echo Socket ID is %d\r\n",g_iEchoSocketID); }#if TCP_IS_NOBOLCK//设置成非阻塞形式,经检测,远端断开连接时不会发生中断,通知远端断开连接 enableOption.NonblockingEnabled = 1; sl_SetSockOpt(g_iEchoSocketID,SL_SOL_SOCKET,SL_SO_NONBLOCKING, (_u8 *)&enableOption,sizeof(enableOption)); // Enable/disable nonblocking mode#endif MAP_UtilsDelay(8000000); }#if TCP_IS_NOBOLCK //当设置成非阻塞的时候,远端断开并不会导致中断发生,为了检测远端有没有断开这个连接 //需要我们去主动的发送,如果发送不成功就是断开连接了 iHeartBeatCounter++; if ((iHeartBeatCounter % 5) == 0){ iStatus = sl_Send(g_iEchoSocketID, "1:这是一个心跳机制的信息", sizeof("这是一个心跳机制的信息"), 0 ); if( iStatus < 0 ){ UART_PRINT("\r\n1:发送失败 \r\n"); sl_Close(g_iEchoSocketID); g_iEchoSocketID = 0; } }#endif //接收数据,这个接收可能是阻塞的也可能是非阻塞的,取决你的设置 iRevLen = sl_Recv(g_iEchoSocketID,szRevBuf,100,0); if (iRevLen > 0) {iStatus = sl_Send(g_iEchoSocketID, szRevBuf, iRevLen, 0 );if( iStatus < 0 ){UART_PRINT("\r\n1:发送失败 \r\n");sl_Close(g_iEchoSocketID);g_iEchoSocketID = 0;} } else { UART_PRINT("\r\n1:%d 没有收到数据 %d \r\n",g_iEchoSocketID,iRevLen);#if TCP_IS_NOBOLCK == 0 UART_PRINT("\r\nsocket 1 断开连接了\r\n"); g_iEchoSocketID = 0;#endif }#if TCP_IS_NOBOLCK //当是非阻塞的时候,需要主动让任务睡眠,切换任务 osi_Sleep(1000);#endif }}void TcpEchoClient2(void *pvParameters){ SlSockAddrIn_t sAddr; SlSockNonblocking_t enableOption; SlSockKeepalive_t xKeepaliveEnableOption; unsigned int ulDestiantionIP; char szRevBuf[100]; int iRevLen,iAddrSize,iStatus; int iHeartBeatCounter = 0; //filling the TCP server socket address sAddr.sin_family = SL_AF_INET; sAddr.sin_port = sl_Htons((unsigned short)9000); siIp_StrToInt("192.168.3.27",&ulDestiantionIP); sAddr.sin_addr.s_addr = sl_Htonl((unsigned int)ulDestiantionIP); iAddrSize = sizeof(SlSockAddrIn_t); UART_PRINT("\r\nTcpEchoClient2\r\n"); while(1) { osi_Sleep(2000); if (g_iEchoSocketID2 == 0) { // creating a TCP socket g_iEchoSocketID2 = sl_Socket(SL_AF_INET,SL_SOCK_STREAM, 0); if( g_iEchoSocketID2 < 0 ) { } // connecting to TCP server iStatus = sl_Connect(g_iEchoSocketID2, ( SlSockAddr_t *)&sAddr, iAddrSize); if( iStatus < 0 ) { // error sl_Close(g_iEchoSocketID2); }else { UART_PRINT("\r\n2:Echo Socket ID is %d\r\n",g_iEchoSocketID2); }#if TCP_IS_NOBOLCK//设置成非阻塞形式,经检测,远端断开连接时不会发生中断,通知远端断开连接 enableOption.NonblockingEnabled = 1; sl_SetSockOpt(g_iEchoSocketID2,SL_SOL_SOCKET,SL_SO_NONBLOCKING, (_u8 *)&enableOption,sizeof(enableOption)); #endif MAP_UtilsDelay(8000000); }#if TCP_IS_NOBOLCK iHeartBeatCounter++; if ((iHeartBeatCounter % 5) == 0){ iStatus = sl_Send(g_iEchoSocketID2, "2:这是一个心跳机制的信息", sizeof("这是一个心跳机制的信息"), 0 ); if( iStatus < 0 ){ UART_PRINT("\r\n2:发送失败 \r\n"); sl_Close(g_iEchoSocketID2); g_iEchoSocketID2 = 0; } }#endif iRevLen = sl_Recv(g_iEchoSocketID2,szRevBuf,100,0); if (iRevLen > 0) {iStatus = sl_Send(g_iEchoSocketID2, szRevBuf, iRevLen, 0 );if( iStatus < 0 ){// error、UART_PRINT("\r\n2:发送失败 \r\n");sl_Close(g_iEchoSocketID2);g_iEchoSocketID2 = 0;} } else { UART_PRINT("\r\n2:%d 没有收到数据 %d \r\n",g_iEchoSocketID,iRevLen);#if TCP_IS_NOBOLCK == 0 UART_PRINT("\r\nsocket 2 断开连接了\r\n"); g_iEchoSocketID2 = 0;#endif }#if TCP_IS_NOBOLCK osi_Sleep(1000);#endif }}
宏定义
#define TcpEchoClient_STACK_SIZE 2048#define TcpEchoClient_PRIORITY 3#define TCP_IS_NOBOLCK 1/* AP Security Parameters */SlSecParams_t SecurityParams = {0};int g_iEchoSocketID = 0;int g_iEchoSocketID2 = 0;
其他函数
/** * @brief 把字符性的ip转成整形的ip * 譬如“192.179.1.1” -->0xc0a0101 * 返回 0 成功 * - 1 失败, * 请注意这个函数最好是输入符合“192.179.1.1”这样形式的 */signed int siIp_StrToInt(char *cpIp,unsigned int *uipIp) { unsigned int retIp,temp; unsigned char i,str[20],*p,*a[5]={0}; i = 0 ; p = str; strncpy(p,cpIp,16); retIp = 0; while((a[i] = strtok(p,".")) != NULL) { p = NULL; temp = strtoul(a[i],0,10); retIp <<= 8; retIp |= temp; i++; } if (i == 4) { *uipIp = retIp; return 0; } else { return -1; }}
1 0
- 一起学习CC3200系列教程之2个TCP_非阻塞及阻塞设置
- 一起学习CC3200系列教程之看门狗
- 一起学习CC3200系列教程之常见问题
- 一起学习CC3200系列教程之CC3200简介
- 一起学CC3200系列教程之中断优先级设置
- 一起学习CC3200系列教程之PWM模式
- 一起学习CC3200系列教程之HttpServer前序
- 一起学习CC3200系列教程之Yeelink传数据
- 一起学习CC3200系列教程之SDK简介
- 一起学习CC3200系列教程之TCP ECHO 服务端 selcet
- 一起学习CC3200系列教程之TCP 速度 测试 netio
- 一起学CC3200系列教程之定时器
- 一起学CC3200系列教程之Systick
- 一起学CC3200系列教程之跑马灯---寄存器版
- 一起学CC3200系列教程之跑马灯---库
- 一起学CC3200系列教程之串口--库函数
- 一起学CC3200系列教程之ADC采集
- 一起学CC3200系列教程之跑马灯---库
- 【iOS官方文档翻译】iOS蓝牙的基本概念
- leetcode第38题-Count and Say
- C语言基础(linux)
- 微博项目
- UVA11992:Fast Matrix Operations(线段树)
- 一起学习CC3200系列教程之2个TCP_非阻塞及阻塞设置
- ubuntu 安装Tkinter, ImageTk...
- 【PAT】自测2 素数对猜想
- Android模拟器按键对应的键盘按键
- 使用Google CPU Profiler对C/C++多线程程序做性能剖析
- 简述UIControl事件的用法
- 常用开发语言小技巧(一)
- HTML5摇一摇
- pandas学习(三)