一起学习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
原创粉丝点击