客户端在等待接受信息时 如果 服务器端 异常断开
无法判断已断开网络
recv函数一直傻等
如何设置才可以避免 其陷入等待 ?谢谢
11 个解决方案
#1
设定超时退出。
比方说recv函数所在的任务设置运行超时(可在任务内计时)自动删除此任务,不影响到其它任务执行。
比方说recv函数所在的任务设置运行超时(可在任务内计时)自动删除此任务,不影响到其它任务执行。
#2
用I/O复用(select)去实现超时处理。还有一种是设置一个超时处理,超时之后设置一个错误值并关闭socket
使recv调用返回。
使recv调用返回。
#3
感谢解答
应用了一个超时中断任务 看门狗
在recv时间达到看门狗设定时间后
我设置了函数close(Sock);
经过验证 发现确实关闭了套接字
因为服务器端套显示断开
但是客户端并没有退出recv并返回
任务陷入了无限阻塞中
具体函数这么写的不知道麻烦帮忙看下问题在哪:
建立套接字 并connect服务器的函数略过
以下为连接好后的函数
while(true) //循环recv
{
wdID=wdCreat(); //建立看门狗
wdStart(wdID,sysXXXX,func(abc),0); //设定超时时间
if(recvlen=recv(sockM,buff,bufflen,0) == 0)
{
close(sockM);
break;
}
wdCancle(wdID);
wdDelete(wdID);
}
int abc()
{
close(sockM);
}
我摘主要的内容,超时后可以走abc这个函数 但是关闭套接字后 无法退出recv 函数 更退不出while循环
导致任务无法关闭
请教如何更改
应用了一个超时中断任务 看门狗
在recv时间达到看门狗设定时间后
我设置了函数close(Sock);
经过验证 发现确实关闭了套接字
因为服务器端套显示断开
但是客户端并没有退出recv并返回
任务陷入了无限阻塞中
具体函数这么写的不知道麻烦帮忙看下问题在哪:
建立套接字 并connect服务器的函数略过
以下为连接好后的函数
while(true) //循环recv
{
wdID=wdCreat(); //建立看门狗
wdStart(wdID,sysXXXX,func(abc),0); //设定超时时间
if(recvlen=recv(sockM,buff,bufflen,0) == 0)
{
close(sockM);
break;
}
wdCancle(wdID);
wdDelete(wdID);
}
int abc()
{
close(sockM);
}
我摘主要的内容,超时后可以走abc这个函数 但是关闭套接字后 无法退出recv 函数 更退不出while循环
导致任务无法关闭
请教如何更改
#4
首先说明一下,由于WDOG是在DEC中间中执行的,所以直接调用close等是错误的,可以在里面用excJobAdd由tExcTask来完成这些执行。不过为了方便我下面就只更正一上编码错误了。
本端关闭之后再去recv应该是返回失败,你这里直接用==0判断会导致死循环吧。而且你这里反复地创建WDOG也会导致内存泄露吧。WDOG没有刷新的函数,可以取消之后重新开始,示例:
int iTmOut = 0;
wdID = wdCreate();
for ( ; ; )
{
wdStart(wdID, XXX, MyTmOut, &iTmOut);
if ((recvlen = recv(sockM, buff, bufflen, 0)) <= 0)
{
if (0 == iTmOut)
{
// 对端关闭
close(sockM);
}
break;
}
// ......
}
int MyTmOut(int *pVal)
{
*pVal = 1;
close(sockM);
}
当然最好是用半关闭,这样close之前就不用再判断了。
本端关闭之后再去recv应该是返回失败,你这里直接用==0判断会导致死循环吧。而且你这里反复地创建WDOG也会导致内存泄露吧。WDOG没有刷新的函数,可以取消之后重新开始,示例:
int iTmOut = 0;
wdID = wdCreate();
for ( ; ; )
{
wdStart(wdID, XXX, MyTmOut, &iTmOut);
if ((recvlen = recv(sockM, buff, bufflen, 0)) <= 0)
{
if (0 == iTmOut)
{
// 对端关闭
close(sockM);
}
break;
}
// ......
}
int MyTmOut(int *pVal)
{
*pVal = 1;
close(sockM);
}
当然最好是用半关闭,这样close之前就不用再判断了。
#5
Sorry,刚才代码中忘了写全:
if ((recvlen = recv(sockM, buff, bufflen, 0)) <= 0)
{
if (0 == iTmOut)
{
// 对端关闭
close(sockM);
}
break;
}
wdCancel(wdID);
if ((recvlen = recv(sockM, buff, bufflen, 0)) <= 0)
{
if (0 == iTmOut)
{
// 对端关闭
close(sockM);
}
break;
}
wdCancel(wdID);
#6
调用wdstart有问题.
#7
调用 s1 = accept(sd, (struct sockaddr *)&their_addr, &addr_len);
i = setsockopt(s1,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
i = setsockopt(s1,SOL_SOCKET,SO_SNDTIMEO,&timeout,sizeof(timeout));
好象不好使!
i = setsockopt(s1,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
i = setsockopt(s1,SOL_SOCKET,SO_SNDTIMEO,&timeout,sizeof(timeout));
好象不好使!
#8
楼上的,这两个选项在VxWorks协议栈中是不支持的。
#9
这两个选项是支持的,请问你的vxWorks版本号是多少?
#10
我用过5.x。
#11
楼主您好,是否可以尝试将套接字设置为非阻塞方式?
blBlockflag = TRUE;//设置为非阻塞方式
ioctl(socket, FIONBIO, (INT32)&blBlockflag);
我写的代码是调用read()//此时read()不会阻塞,立刻返回
如果返回 -1 则表示超时
如果返回 0 表示对端关闭了socket
如果返回正数,表示接受到的字节数
这样,你就可以通过一个循环来实现超时退出了
/* 下面是我程序里的一部分,是要读取1个字节的启动字符 */
while (dwCounter < 30000)
{
n = read(dwFd, (CHAR *)&cStartChar, 1);
if (n == 0)
{
return NULL;//对端关闭了链路
}
if (n == -1)
{
dwCounter++;
taskDelay(1);
continue;
}
if (n != 1)
{
#ifdef P102IODEBUG
logMsg("读取启动字符失败!!!\n", 0,0,0,0,0,0);
#endif
cStartChar = 0;
continue;
}
break;
}
不知道这样的方法在楼主的程序里是否可行,
我们使用的接口不同,
但是应该有类似的方式。
blBlockflag = TRUE;//设置为非阻塞方式
ioctl(socket, FIONBIO, (INT32)&blBlockflag);
我写的代码是调用read()//此时read()不会阻塞,立刻返回
如果返回 -1 则表示超时
如果返回 0 表示对端关闭了socket
如果返回正数,表示接受到的字节数
这样,你就可以通过一个循环来实现超时退出了
/* 下面是我程序里的一部分,是要读取1个字节的启动字符 */
while (dwCounter < 30000)
{
n = read(dwFd, (CHAR *)&cStartChar, 1);
if (n == 0)
{
return NULL;//对端关闭了链路
}
if (n == -1)
{
dwCounter++;
taskDelay(1);
continue;
}
if (n != 1)
{
#ifdef P102IODEBUG
logMsg("读取启动字符失败!!!\n", 0,0,0,0,0,0);
#endif
cStartChar = 0;
continue;
}
break;
}
不知道这样的方法在楼主的程序里是否可行,
我们使用的接口不同,
但是应该有类似的方式。
#1
设定超时退出。
比方说recv函数所在的任务设置运行超时(可在任务内计时)自动删除此任务,不影响到其它任务执行。
比方说recv函数所在的任务设置运行超时(可在任务内计时)自动删除此任务,不影响到其它任务执行。
#2
用I/O复用(select)去实现超时处理。还有一种是设置一个超时处理,超时之后设置一个错误值并关闭socket
使recv调用返回。
使recv调用返回。
#3
感谢解答
应用了一个超时中断任务 看门狗
在recv时间达到看门狗设定时间后
我设置了函数close(Sock);
经过验证 发现确实关闭了套接字
因为服务器端套显示断开
但是客户端并没有退出recv并返回
任务陷入了无限阻塞中
具体函数这么写的不知道麻烦帮忙看下问题在哪:
建立套接字 并connect服务器的函数略过
以下为连接好后的函数
while(true) //循环recv
{
wdID=wdCreat(); //建立看门狗
wdStart(wdID,sysXXXX,func(abc),0); //设定超时时间
if(recvlen=recv(sockM,buff,bufflen,0) == 0)
{
close(sockM);
break;
}
wdCancle(wdID);
wdDelete(wdID);
}
int abc()
{
close(sockM);
}
我摘主要的内容,超时后可以走abc这个函数 但是关闭套接字后 无法退出recv 函数 更退不出while循环
导致任务无法关闭
请教如何更改
应用了一个超时中断任务 看门狗
在recv时间达到看门狗设定时间后
我设置了函数close(Sock);
经过验证 发现确实关闭了套接字
因为服务器端套显示断开
但是客户端并没有退出recv并返回
任务陷入了无限阻塞中
具体函数这么写的不知道麻烦帮忙看下问题在哪:
建立套接字 并connect服务器的函数略过
以下为连接好后的函数
while(true) //循环recv
{
wdID=wdCreat(); //建立看门狗
wdStart(wdID,sysXXXX,func(abc),0); //设定超时时间
if(recvlen=recv(sockM,buff,bufflen,0) == 0)
{
close(sockM);
break;
}
wdCancle(wdID);
wdDelete(wdID);
}
int abc()
{
close(sockM);
}
我摘主要的内容,超时后可以走abc这个函数 但是关闭套接字后 无法退出recv 函数 更退不出while循环
导致任务无法关闭
请教如何更改
#4
首先说明一下,由于WDOG是在DEC中间中执行的,所以直接调用close等是错误的,可以在里面用excJobAdd由tExcTask来完成这些执行。不过为了方便我下面就只更正一上编码错误了。
本端关闭之后再去recv应该是返回失败,你这里直接用==0判断会导致死循环吧。而且你这里反复地创建WDOG也会导致内存泄露吧。WDOG没有刷新的函数,可以取消之后重新开始,示例:
int iTmOut = 0;
wdID = wdCreate();
for ( ; ; )
{
wdStart(wdID, XXX, MyTmOut, &iTmOut);
if ((recvlen = recv(sockM, buff, bufflen, 0)) <= 0)
{
if (0 == iTmOut)
{
// 对端关闭
close(sockM);
}
break;
}
// ......
}
int MyTmOut(int *pVal)
{
*pVal = 1;
close(sockM);
}
当然最好是用半关闭,这样close之前就不用再判断了。
本端关闭之后再去recv应该是返回失败,你这里直接用==0判断会导致死循环吧。而且你这里反复地创建WDOG也会导致内存泄露吧。WDOG没有刷新的函数,可以取消之后重新开始,示例:
int iTmOut = 0;
wdID = wdCreate();
for ( ; ; )
{
wdStart(wdID, XXX, MyTmOut, &iTmOut);
if ((recvlen = recv(sockM, buff, bufflen, 0)) <= 0)
{
if (0 == iTmOut)
{
// 对端关闭
close(sockM);
}
break;
}
// ......
}
int MyTmOut(int *pVal)
{
*pVal = 1;
close(sockM);
}
当然最好是用半关闭,这样close之前就不用再判断了。
#5
Sorry,刚才代码中忘了写全:
if ((recvlen = recv(sockM, buff, bufflen, 0)) <= 0)
{
if (0 == iTmOut)
{
// 对端关闭
close(sockM);
}
break;
}
wdCancel(wdID);
if ((recvlen = recv(sockM, buff, bufflen, 0)) <= 0)
{
if (0 == iTmOut)
{
// 对端关闭
close(sockM);
}
break;
}
wdCancel(wdID);
#6
调用wdstart有问题.
#7
调用 s1 = accept(sd, (struct sockaddr *)&their_addr, &addr_len);
i = setsockopt(s1,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
i = setsockopt(s1,SOL_SOCKET,SO_SNDTIMEO,&timeout,sizeof(timeout));
好象不好使!
i = setsockopt(s1,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
i = setsockopt(s1,SOL_SOCKET,SO_SNDTIMEO,&timeout,sizeof(timeout));
好象不好使!
#8
楼上的,这两个选项在VxWorks协议栈中是不支持的。
#9
这两个选项是支持的,请问你的vxWorks版本号是多少?
#10
我用过5.x。
#11
楼主您好,是否可以尝试将套接字设置为非阻塞方式?
blBlockflag = TRUE;//设置为非阻塞方式
ioctl(socket, FIONBIO, (INT32)&blBlockflag);
我写的代码是调用read()//此时read()不会阻塞,立刻返回
如果返回 -1 则表示超时
如果返回 0 表示对端关闭了socket
如果返回正数,表示接受到的字节数
这样,你就可以通过一个循环来实现超时退出了
/* 下面是我程序里的一部分,是要读取1个字节的启动字符 */
while (dwCounter < 30000)
{
n = read(dwFd, (CHAR *)&cStartChar, 1);
if (n == 0)
{
return NULL;//对端关闭了链路
}
if (n == -1)
{
dwCounter++;
taskDelay(1);
continue;
}
if (n != 1)
{
#ifdef P102IODEBUG
logMsg("读取启动字符失败!!!\n", 0,0,0,0,0,0);
#endif
cStartChar = 0;
continue;
}
break;
}
不知道这样的方法在楼主的程序里是否可行,
我们使用的接口不同,
但是应该有类似的方式。
blBlockflag = TRUE;//设置为非阻塞方式
ioctl(socket, FIONBIO, (INT32)&blBlockflag);
我写的代码是调用read()//此时read()不会阻塞,立刻返回
如果返回 -1 则表示超时
如果返回 0 表示对端关闭了socket
如果返回正数,表示接受到的字节数
这样,你就可以通过一个循环来实现超时退出了
/* 下面是我程序里的一部分,是要读取1个字节的启动字符 */
while (dwCounter < 30000)
{
n = read(dwFd, (CHAR *)&cStartChar, 1);
if (n == 0)
{
return NULL;//对端关闭了链路
}
if (n == -1)
{
dwCounter++;
taskDelay(1);
continue;
}
if (n != 1)
{
#ifdef P102IODEBUG
logMsg("读取启动字符失败!!!\n", 0,0,0,0,0,0);
#endif
cStartChar = 0;
continue;
}
break;
}
不知道这样的方法在楼主的程序里是否可行,
我们使用的接口不同,
但是应该有类似的方式。