当前位置: 技术问答>linux和unix
使用TCP,在客户端怎么知道建立好的连接已经断开?怎么用非阻塞模式,以及怎么知道socket已经收到数据并立即将数据读出?
来源: 互联网 发布时间:2015-12-06
本文导语: 谢谢 | 你所有问题的答案是select 或pselect 调用。 下面是我的程序一段,为你摘录出来主体。 这是发送,看socket是否可以发送,可以则发送,不可以则尝试直到ntimeout秒后。 fd_set...
谢谢
|
你所有问题的答案是select 或pselect 调用。
下面是我的程序一段,为你摘录出来主体。
这是发送,看socket是否可以发送,可以则发送,不可以则尝试直到ntimeout秒后。
fd_set wfds;
FD_ZERO(&wfds);
FD_SET(socket,&wfds);
struct timeval tmout;
tmout.tv_sec=ntimeout;
tmout.tv_usec=0;
int nselect=select(1024,NULL,&wfds,NULL,&tmout);
if(nselect==-1)
{
//select调用错误,报告错误,一般通过errno
}
else if(nselect)
{
//可写进行发送(网络物理和传输链路OK)
int sret;
sret=send(socket,....);
if(sret==-1){
//Send出错,检查或报告错误,一般通过errno
}
}
else
{
//不可写,连接问题,检查或报告错误,一般通过errno
shutdown(socket,SHUT_RDWR);
close(socket);
}
这是接收部分,同发送过程基本相同,除了rfds的位置。
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(socket,&rfds);
struct timeval tmout;
tmout.tv_sec=ntimeout;
tmout.tv_usec=0;
int nselect=select(1024,&rfds,NULL,NULL,&tmout);
if(nselect==-1)
{
//select调用错误,报告错误,一般通过errno
}
else if(nselect)
{
//可读,进行接收(网络物理和传输链路OK,且有income数据)
int sret;
sret=recv(socket,....);
if(sret==-1){
//recv出错,检查或报告错误,一般通过errno
}
}
else
{
//不可读,连接问题或无数据可读,检查或报告错误,一般通过errno
shutdown(socket,SHUT_RDWR);
close(socket);
}
如果你想connect时使用异步模式(看是否可以连接,否则超时退出),基本同send过程,用select询问是否可写即可。因为connect过程基本就是先send SYN到服务器,然后接收SYN+ACK,然后再发ACK
下面是我的程序一段,为你摘录出来主体。
这是发送,看socket是否可以发送,可以则发送,不可以则尝试直到ntimeout秒后。
fd_set wfds;
FD_ZERO(&wfds);
FD_SET(socket,&wfds);
struct timeval tmout;
tmout.tv_sec=ntimeout;
tmout.tv_usec=0;
int nselect=select(1024,NULL,&wfds,NULL,&tmout);
if(nselect==-1)
{
//select调用错误,报告错误,一般通过errno
}
else if(nselect)
{
//可写进行发送(网络物理和传输链路OK)
int sret;
sret=send(socket,....);
if(sret==-1){
//Send出错,检查或报告错误,一般通过errno
}
}
else
{
//不可写,连接问题,检查或报告错误,一般通过errno
shutdown(socket,SHUT_RDWR);
close(socket);
}
这是接收部分,同发送过程基本相同,除了rfds的位置。
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(socket,&rfds);
struct timeval tmout;
tmout.tv_sec=ntimeout;
tmout.tv_usec=0;
int nselect=select(1024,&rfds,NULL,NULL,&tmout);
if(nselect==-1)
{
//select调用错误,报告错误,一般通过errno
}
else if(nselect)
{
//可读,进行接收(网络物理和传输链路OK,且有income数据)
int sret;
sret=recv(socket,....);
if(sret==-1){
//recv出错,检查或报告错误,一般通过errno
}
}
else
{
//不可读,连接问题或无数据可读,检查或报告错误,一般通过errno
shutdown(socket,SHUT_RDWR);
close(socket);
}
如果你想connect时使用异步模式(看是否可以连接,否则超时退出),基本同send过程,用select询问是否可写即可。因为connect过程基本就是先send SYN到服务器,然后接收SYN+ACK,然后再发ACK
|
三个问题:
1。使用TCP,在客户端怎么知道建立好的连接已经断开?
read返回0
2。怎么用非阻塞模式?
fcntl()
3。以及怎么知道socket已经收到数据并立即将数据读出?
可以用select,也可以用阻塞或非阻塞read. 在linux下对tcp socket来说你可以把它当成一个流文件看。
1。使用TCP,在客户端怎么知道建立好的连接已经断开?
read返回0
2。怎么用非阻塞模式?
fcntl()
3。以及怎么知道socket已经收到数据并立即将数据读出?
可以用select,也可以用阻塞或非阻塞read. 在linux下对tcp socket来说你可以把它当成一个流文件看。
|
要想“立即”(当然也是相当而言)知道一个连接已经断开,可以使用心跳函数。
如果不关心时效性,则客户端在第二次写已断开的socket的时候会产生EPIPE。
你所有的这些问题在《unix网络编程》卷一中都有答案,你不妨找来看一下。
如果不关心时效性,则客户端在第二次写已断开的socket的时候会产生EPIPE。
你所有的这些问题在《unix网络编程》卷一中都有答案,你不妨找来看一下。
|
我的blog上有一个epoll的例子
http://blog.chinaunix.net/u/1574/showart.php?id=31992
http://blog.chinaunix.net/u/1574/showart.php?id=31992
|
int set_fd(int fd)
{
int flag;
if(flag=fcntl(fd,F_GETFL)
{
int flag;
if(flag=fcntl(fd,F_GETFL)