各位大神。。。帮帮我呗。。。我特别困惑
我在STM32F2系列下用select方式开发TCP服务端,每个服务端可以接收多个链接,
我每个链接都设置成了非阻塞模式,在TCP通讯过程中反复插拔网线,偶尔会出现SELECT任务被挂起的情况,我加了mark,在recv前的mark = recv后mark+1,然后任务被挂起。。。。请帮帮我
我的具体代码如下:
if(s_NetRunFlag == 0)
{
Net_Initialize();
// allocate a socket
ts_sock_m = socket(AF_INET, SOCK_STREAM, 0);
if (ts_sock_m < 0)
{
return; // Couldn’t Allocate a TCP Socket
}
// Bind the socket to the local port number and IP address
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(net_astIp[0].port_no);
// port number in network byte order
memcpy((int8_t *)&sin.sin_addr, (int8_t *)net_astIp[0].ip_server_address, 4);
if (bind(ts_sock_m, (const struct sockaddr *)&sin, sizeof(sin)) < 0)
{
closesocket(ts_sock_m);
return; // Bind Failed
}
if (listen(ts_sock_m, NET_MAX_LINK) != 0) // 2 slave ports
{
closesocket(ts_sock_m);
return; // Listen Failed
}
/*设置非阻塞模式*/
ioctlsocket(ts_sock_m,FIONBIO,&nMode);
FD_ZERO(&rset);
FD_ZERO(&allset);
FD_SET(ts_sock_m, &rset);
maxfd = ts_sock_m;
timeout.tv_sec = 30;
timeout.tv_usec = 0;
s_NetRunFlag = 1;
}
while (1)
{
FD_ZERO(&rset);
FD_SET(ts_sock_m, &rset);
for (i = 0; i < NET_MAX_LINK; i++)
{
if (net_astRecv0[i].ts_sock_s != -1)
{
FD_SET(net_astRecv0[i].ts_sock_s, &rset);
}
}
iSelectRet = select(maxfd + 1, &rset, NULL, NULL, &timeout);
if(iSelectRet < 0)
{/*错误*/
yj_slect_err++;
continue;
}
else if(iSelectRet == 0)
{/*超时*/
yj_slect_0++;
for (i = 0; i <= maxi; i++)
{
ts_sock_s = net_astRecv0[i].ts_sock_s;
if(ts_sock_s >= 0)
{/*文件描述符不大于0*/
closesocket(ts_sock_s);
FD_CLR(net_astRecv0[i].ts_sock_s, &rset);
net_astRecv0[i].ts_sock_s = -1;
net_astRecv0[i].ulTaskId = 0;
}
}
maxi = 0;
continue;
}
else
{
yj_slect_OK++;
for (i = 0; i <= maxi; i++)
{
ts_sock_s = net_astRecv0[i].ts_sock_s;
if (FD_ISSET(ts_sock_s, &rset))
{/*有链接则接收数据*/
yj_recv_start++;
n_received = recv(ts_sock_s, (int8_t *)stNetMsg.aucData, sizeof(stNetMsg.aucData), 0);
if (n_received <= 0)
{
closesocket(ts_sock_s);
FD_CLR(net_astRecv0[i].ts_sock_s, &rset);
net_astRecv0[i].ts_sock_s = -1;
net_astRecv0[i].ulTaskId = 0;
yj_err_message[yj_recv_err] = n_received;
yj_recv_err++;
}
else
{
yj_recv++;
stNetMsg.usLength = n_received;
stNetMsg.ulTaskId = net_astRecv0[i].ulTaskId;
stNetMsg.ucRtNum = i;
stNetMsg.ucLtNum = NET_LISTEN_TASK0;
if ((stNetMsg.usLength > 7) &&
(stNetMsg.aucData[2] == 0x00) &&
(stNetMsg.aucData[3] == 0x00))
{
memcpy(&usLen, stNetMsg.aucData + 4, 2);
if (usLen == (unsigned short)(stNetMsg.usLength - 6))
{
xQueueSend(xCtrlQueueHandle, &stNetMsg, 0);
}
}
}
}
}
if (FD_ISSET(ts_sock_m, &rset))
{/*创建新的链接*/
yj_acceptstart++;
sin_len = sizeof(struct sockaddr_in);
ts_sock_s = accept(ts_sock_m, (struct sockaddr *)&sin, (socklen_t *)&sin_len);
yj_accept++;
if (ts_sock_s == -1)
{
continue;
}
/*设置非阻塞模式*/
nMode = 1;
ioctlsocket(ts_sock_s,FIONBIO,&nMode);
for (i = 0; i < NET_MAX_LINK; i++)
{
if (net_astRecv0[i].ts_sock_s < 0)
{
net_astRecv0[i].ts_sock_s= ts_sock_s;
if (i > maxi)
maxi = i;
break;
}
}
if (ts_sock_s > maxfd)
maxfd = ts_sock_s;
}
}
osDelay(1);
}
}
close socket需要足够的释放时间,我测试这个时间大于10S. 否则会导致bind失败