|
板子做client端,创建两个任务连接task1 task2,task连接10000端口的服务器1,task2连接10001的服务器2,现在出现的问题是,如果上电直接运行,会造成两个客户端都无法连接,在线监测发现通过socket申请的端口号都一样,只要在两个任务里分别设置一个断点就能连接上了。不然两个服务器都无法连接或者偶尔能连接上,但两个客户端都连接的同一个服务器,但在程序了每个任务都指定了不同的端口号的服务器。请问一下这个应该是什么问题?- #include "bsp_net.h"
- #include "bsp_json.h"
- #include "string.h"
- int sock1;
- SOCKADDR_IN addr1;
- int sock2;
- SOCKADDR_IN addr2;
- /*
- *********************************************************************************************************
- * 函 数 名: vTaskSocket10001
- * 功能说明: 控制通信任务
- * 形 参: 无
- * 返 回 值: 无
- *********************************************************************************************************
- */
- void vTaskSocket10001(void *arg)
- {
- char sendbuf[500] = {0};
- uint8_t recvbuf[500] = {0};
- uint8_t cmd = 0,i;
- uint16_t len = 0;
- int res;
- unsigned long sck_mode = 1;
-
- while (1) //客户端断开可以在重新进行连接
- {
- sock1 = socket (AF_INET, SOCK_STREAM, 0);
- res = ioctlsocket (sock1, FIO_KEEP_ALIVE, &sck_mode); /* 设置使能KEEP ALIVE,让客户端和服务器保存连接 */
- addr1.sin_port = htons(8089); /* 端口号设置为1001 */
- addr1.sin_family = PF_INET; /* 与函数socket中的AF_INET作用一样 */
- addr1.sin_addr.s_b1 = server_ip1;
- addr1.sin_addr.s_b2 = server_ip2;
- addr1.sin_addr.s_b3 = server_ip3;
- addr1.sin_addr.s_b4 = server_ip4;
- res = connect (sock1, (SOCKADDR *)&addr1, sizeof (addr1)); /* 客户端连接远程服务器,如果远程服务器还未创建,此函数会立即返回 */
- while (1)
- {
- res = recv (sock1, (char *)recvbuf, sizeof(recvbuf), 0);
- if (res <= 0)
- {
- if((res == SCK_EINVALID) || (res == SCK_ECLOSED))
- {
- goto err;
- }
- }
- else
- {
- cmd = control_treatment(recvbuf); //解析接收到的数据
- len = control_generation(sendbuf,cmd); //根据接收的数据进行返回数据
- again:
- res = send (sock1, (char *)sendbuf, len,0);//+14+2, 0);
- if (res < 0)
- {
- //sock句柄无效 sock已经关闭了 底层通信出错
- if((res == SCK_EINVALID)||(res == SCK_ECLOSED)||(res == SCK_ERROR))
- {
- goto err;
- }
- else//非以上必须重连的情况,直接进行重发,后期可以优化针对阻塞才重发
- {
- goto again;
- }
- }
- }
- vTaskDelay(10);
- }
- err:
- while(1)//释放sock失败需要重新的调用,所以做循环处理
- {
- if(closesocket (sock1) != SCK_EWOULDBLOCK)
- break;
-
- vTaskDelay(1000);
- }
- vTaskDelay(2000);
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: vTaskSocket10000
- * 功能说明: 实时传输数据通信任务
- * 形 参: 任务传递参数
- * 返 回 值: 本任务内需要用到一些sock等参数,直接全部在内部进行封装处理数据
- *********************************************************************************************************
- */
- void vTaskSocket10000(void *arg)
- {
- int res; //send recv函数使用
- unsigned long sck_mode;
-
- while (1)
- {
- sock2 = socket (AF_INET, SOCK_STREAM, 0);
- sck_mode = 1;
- res = ioctlsocket (sock2, FIO_KEEP_ALIVE, &sck_mode);
- if (res == SCK_SUCCESS)
- {
- }
- else
- {
- }
- addr2.sin_port = htons(8089);/* 端口号设置为1001 */
- addr2.sin_family = PF_INET;/* 与函数socket中的AF_INET作用一样 */
- addr2.sin_addr.s_b1 = server_ip1;
- addr2.sin_addr.s_b2 = server_ip2;
- addr2.sin_addr.s_b3 = server_ip3;
- addr2.sin_addr.s_b4 = server_ip4;
- res = connect (sock2, (SOCKADDR *)&addr2, sizeof (addr2));/* 客户端连接远程服务器,如果远程服务器还未创建,此函数会立即返回 */
- while (1)
- {
- if(Parameter_Setting.RunStop == true)
- {
- res = send (sock2, (const char *)sendbuf, len, 0);
- if (res < 0)//发送失败的情况
- {
- //sock句柄无效 sock已经关闭了 底层通信出错
- if((res == SCK_EINVALID)||(res == SCK_ECLOSED)||(res == SCK_ERROR))
- {
- goto err;
- }
- res = recv (sock2, recvbuf, sizeof(recvbuf), 0); //接收数据
- if (res <= 0)
- {
- //同上发送出错机制
- if((res == SCK_EINVALID) || (res == SCK_ECLOSED))
- {
- goto err; //出错后直接通过goto跳转
- }
- }
- }
- }
- else//非运行状态,发送心跳
- {
- sprintf((char *)sendbuf->buf,"{"Cmd":0,"Sync":%d}",sync_con_1++);
- again_stop: //发送数据有时会存在失败,用goto进行重发
- len = strlen((const char *)sendbuf->buf);//计算发送数据的长度,后期把send的函数的长度进行增加头尾长度暂时未加
- // sendbuf->buf[len] = 0xee;
- // sendbuf->buf[len+1] = 0xee;
- res = send (sock2, (const char *)sendbuf, len, 0);
- if (res < 0)//发送失败的情况
- {
- //sock句柄无效 sock已经关闭了 底层通信出错
- if((res == SCK_EINVALID)||(res == SCK_ECLOSED)||(res == SCK_ERROR))
- {
- goto err;
- }
- else//非以上必须重连的情况,直接进行重发,后期可以优化针对阻塞才重发
- {
- goto again_stop;
- }
- }
- else//发送成功
- {
-
- }
- res = recv (sock2, recvbuf, sizeof(recvbuf), 0); //接收数据
- if (res <= 0)
- {
- //同上发送出错机制
- if((res == SCK_EINVALID) || (res == SCK_ECLOSED))
- {
- goto err; //出错后直接通过goto跳转
- }
- }
- }
- vTaskDelay(5000);
- }
- err:
- while(1)//关闭sock失败时要重复调用
- {
- if(closesocket (sock2) != SCK_EWOULDBLOCK)
- break;
- vTaskDelay(500);
- }
- vTaskDelay(1000);
- }
- }
- /*
- *********************************************************************************************************
- * 函 数 名: vTaskTCPnet
- * 功能说明: RL-TCPnet网络主任务
- * 形 参: pvParameters 是在创建该任务时传递的形参
- * 返 回 值: 无
- * 优 先 级: 5
- *********************************************************************************************************
- */
- void vTaskTCPnet(void *arg)
- {
- while(1)
- {
- /* RL-TCPnet处理函数 */
- xEventGroupWaitBits(xCreatedTCPnetGroup, /* 事件标志组句柄 */
- 0x0001, /* 等待被设置 */
- pdTRUE, /* 退出前bit0被清除 */
- pdFALSE, /* 设置为pdFALSE表示仅等待bit0被设置*/
- portMAX_DELAY); /* 永久等待 */
-
- while (main_TcpNet() == __TRUE);
- }
- }
- /*********************************************************************************************************
- * 函 数 名: vTaskStart
- * 功能说明: 启动任务,也是最高优先级任务,这里实现RL-TCPnet的时间基准更新
- * 形 参: pvParameters 是在创建该任务时传递的形参
- * 返 回 值: 无
- * 优 先 级: 5
- *********************************************************************************************************
- */
- void vTaskTCPStart(void *arg)
- {
- TickType_t xLastWakeTime;
- const TickType_t xFrequency = 100;
-
- /* 初始化RL-TCPnet */
- init_TcpNet ();
-
- /* 获取当前的系统时间 */
- xLastWakeTime = xTaskGetTickCount();
-
- while(1)
- {
- /* RL-TCPnet时间基准更新函数 */
- timer_tick ();
- xEventGroupSetBits(xCreatedTCPnetGroup, 0x0001);
-
- /* vTaskDelayUntil是绝对延迟,vTaskDelay是相对延迟。*/
- vTaskDelayUntil(&xLastWakeTime, xFrequency);
- }
- }
复制代码 部分代码删除了一点,但整体的是根据老大的例子写的
|
|