高级会员
- 积分
- 839
- 金钱
- 839
- 注册时间
- 2016-8-23
- 在线时间
- 116 小时
|
楼主 |
发表于 2023-9-20 18:44:38
|
显示全部楼层
使用以下函数,可以设置非阻塞模式接收数据
bool SetNonBlock(int fd)
{
int res = 0;
int flags = fcntl(fd, F_GETFL, 0);
if(flags < 0)
{
printf("error code: %d, set non block, fcntl get failed\r\n", flags);
return pdFALSE;
}
res = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
if(res < 0)
{
printf("error code: %d, set non block, fcntl set failed\r\n", res);
return pdFALSE;
}
return pdTRUE;
}
具体使用方法如下:
创建一个任务,创建服务端tcp socket,等待客户端连接。等客户端连接后再创建一个接收网络数据任务
void server_run_task(void *arg)
{
int ret = 0;
uint32_t len = 0;
int tcp_port = 42552;
struct sockaddr_in svr_addr, clt_addr;
int opt = 1;
while(1)
{
/* bind to port 42552 at any interface */
memset(&svr_addr, 0, sizeof(svr_addr));
svr_addr.sin_family = AF_INET;
svr_addr.sin_port = htons(tcp_port);
svr_addr.sin_addr.s_addr = htonl(INADDR_ANY);
/* create a TCP socket */
main_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(main_sockfd < 0)
{
printf("socket error\r\n");
continue;
}
ret = bind(main_sockfd, (struct sockaddr *)&svr_addr, sizeof(svr_addr));
if(ret < 0)
{
lwip_close(main_sockfd);
main_sockfd = -1;
printf("fail to bind\r\n");
continue;
}
/* listen for incoming connections (TCP listen backlog = 1) */
ret = listen(main_sockfd, 1);
if(ret < 0)
{
lwip_close(main_sockfd);
main_sockfd = -1;
printf("listen error\r\n");
continue;
}
len = sizeof(clt_addr);
/* grab new connection */
while(1)
{
client_1_fd = accept(main_sockfd, (struct sockaddr *)&clt_addr, (socklen_t *)&len);
printf("accept!:client_1_fd = %d\r\n", client_1_fd);
if(-1 != client_1_fd)
{
printf("\nconnect\n");
if(CreatRec_result != pdFAIL)
{
if(client_1_fd >= 1)
{
printf("close front_fd:%d\r\n", front_fd);
lwip_close(front_fd);
}
vTaskDelete(TCPServRec_xTask);
CreatRec_result = pdFAIL;
printf("delete server receive\r\n");
}
front_fd = client_1_fd;
printf("front_fd=%d\r\n", front_fd);
mdns_resp_announce(&g_mynetif);
vTaskDelay(5);
CreatRec_result = xTaskCreate(TCPServerRec, "SERVERREC", DEFAULT_THREAD_STACKSIZE,
(int *)&client_1_fd, SERV_REC_PRIO, &TCPServRec_xTask);
if(CreatRec_result == pdFAIL)
{
lwip_close(client_1_fd);
client_1_fd = -1;
continue;
}
}
else
{
lwip_close(client_1_fd);
client_1_fd = -1;
if(CreatRec_result != pdFAIL)
{
vTaskDelete(TCPServRec_xTask);
CreatRec_result = pdFAIL;
printf("delete server receive\r\n");
}
lwip_close(main_sockfd);
main_sockfd = -1;
break;
}
}
}
}
接收网络数据任务,非阻塞模式放在这个函数里设置
void TCPServerRec(void * pvParameters)
{
int recvNum = 0;
uint16_t i = 0;
uint16_t errcount = 0;
BaseType_t notify_result = pdFALSE;
SetNonBlock(client_1_fd); //set non-blocking mode
while(1)
{
vTaskDelay(300); //delay 300ms
recvNum = recv(client_1_fd, Netbuf, MAX_BUF_SIZE, 0);
printf("TCP recv = %d\r\n", recvNum);
if(recvNum > 0)
{
errcount = 0;
for(i=0; i<recvNum; i++)
{
Netrecbuf[Rec_offset] = Netbuf[i];
Rec_offset++;
if(Rec_offset == MAX_BUF_SIZE)
{
Rec_offset = 0;
}
}
notify_result = xTaskNotifyGive(Buffer_parse_xTask);
if(notify_result != pdPASS)
{
printf("Notify fail\n");
}
}
else
{
if((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR))
{
errcount = 0;
continue;
}
errcount++;
if(errcount >= 10)
{
printf("recv error:%d, close normally\r\n", errno);
errcount = 0;
lwip_close(client_1_fd);
client_1_fd = -1;
CreatRec_result = pdFAIL;
vTaskDelete(NULL);
}
}
}
} |
|