当前位置:  技术问答>linux和unix

linux socket如何检测断开

    来源: 互联网  发布时间:2017-02-28

    本文导语:  请教在linux下如何快速检测到socket正常或不正常断开,我想通过recv和send的返回值来判断是否连接异常,但是不成功,下面是我的测试代码,连接成功后如果我断开客户端,那么服务端不会打印错误信息而是等待几秒...

请教在linux下如何快速检测到socket正常或不正常断开,我想通过recv和send的返回值来判断是否连接异常,但是不成功,下面是我的测试代码,连接成功后如果我断开客户端,那么服务端不会打印错误信息而是等待几秒后直接终止;如果断开服务端,客户端的recv不再阻塞,而且返回值一直是0,请高手指点。


//服务端
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MYPORT 3490 /*定义用户连接端口*/
#define BACKLOG 10 /*多少等待连接控制*/
int main(int argc, char *argv[])
{
int sockfd, new_fd;/* listen on sock_fd, new connection on new_fd*/
struct sockaddr_in my_addr; /* my address information */
struct sockaddr_in their_addr; /* connector's address information */
int sin_size;
if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}

int opt = 1;
int len = sizeof(opt);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, len);

my_addr.sin_family = AF_INET; /* host byte order */
my_addr.sin_port = htons(MYPORT); /* short, network byte order */
my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
bzero(&(my_addr.sin_zero),0); /* zero the rest of the struct */

if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))== -1) 
{
perror("bind");
exit(1);
}
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}

while(1) { /* main accept() loop */
sin_size = sizeof(struct sockaddr_in);
printf("whilen");
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1) 
{
perror("accept");
continue;
}
printf("server: got connection from %sn", inet_ntoa(their_addr.sin_addr));

while(1)
{
usleep(10000000);
if (send(new_fd, "Hello, world!n", 14, 0) == -1)
perror("send");
}
close(new_fd);
exit(0);

}
return 0;
}



//客户端
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define PORT 3490 /* 客户机连接远程主机的端口 */
#define MAXDATASIZE 100 /* 每次可以接收的最大字节 */
int main(int argc, char *argv[])
{
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct hostent *he;
struct sockaddr_in their_addr; /* connector's address information */
if (argc != 2) 
{
fprintf(stderr,"usage: client hostnamen");
exit(1);
}
if ((he=gethostbyname(argv[1])) == NULL) 
{ /* get the host info */
herror("gethostbyname");
exit(1);
}

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
{
perror("socket");
exit(1);
}

their_addr.sin_family = AF_INET; /* host byte order */
their_addr.sin_port = htons(PORT); /* short, network byte order */
their_addr.sin_addr = *((struct in_addr *)(he->h_addr));
bzero(&(their_addr.sin_zero),0); /* zero the rest of the struct */
if (connect(sockfd, (struct sockaddr *)&their_addr,sizeof(struct sockaddr)) == -1) 
{
perror("connect");
exit(1);
}
while(1)
{
printf("receiving......n");
if ((numbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1) 
{
perror("recv");
exit(1);
}
buf[numbytes] = '';
printf("Received: %sn",buf);
}
close(sockfd);
return 0;
}



另外,在网上看到一种利用TCP协议栈中的KeepAlive探测的方法,下面是我从网上找的用的比较多的一段代码,这里应该只是设置了一些属性参数,但不知具体怎样在通信中检测断开,请高手赐教。

#include 
……
////KeepAlive实现
//下面代码要求有ACE,如果没有包含ACE,则请把用到的ACE函数改成linux相应的接口
int keepAlive = 1;//设定KeepAlive
int keepIdle = 5;//开始首次KeepAlive探测前的TCP空闭时间
int keepInterval = 5;//两次KeepAlive探测间的时间间隔
int keepCount = 3;//判定断开前的KeepAlive探测次数

if(setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == -1)
{
        ACE_DEBUG ((LM_INFO,
        ACE_TEXT ("(%P|%t) setsockopt SO_KEEPALIVE error!n")));

}

if(setsockopt(s,SOL_TCP,TCP_KEEPIDLE,(void *)&keepIdle,sizeof(keepIdle)) == -1)
{
        ACE_DEBUG ((LM_INFO,
        ACE_TEXT ("(%P|%t) setsockopt TCP_KEEPIDLE error!n")));
}

if(setsockopt(s,SOL_TCP,TCP_KEEPINTVL,(void *)&keepInterval,sizeof(keepInterval)) == -1)
{
        ACE_DEBUG ((LM_INFO,
        ACE_TEXT ("(%P|%t) setsockopt TCP_KEEPINTVL error!n")));
}

if(setsockopt(s,SOL_TCP,TCP_KEEPCNT,(void *)&keepCount,sizeof(keepCount)) == -1)
{
        ACE_DEBUG ((LM_INFO,
        ACE_TEXT ("(%P|%t)setsockopt TCP_KEEPCNT error!n")));
}


|
recv和send不能接收到数据或者不能发送数据,就表示连接已经断开了啊。如果断开了服务器,客户端接收不到数据,当然是一直返回0了

|
我想通过recv和send的返回值来判断是否连接异常,但是不成功,

send只要数据写入发送缓冲区就返回了,这样判断没有用的。

除了心跳包,或者类似的办法,没想到有更好的处理方法。

http://topic.csdn.net/t/20050418/11/3945333.html

|
>>客户端的recv不再阻塞,而且返回值一直是0

recv函数返回0,表明对端已经断开了,你不应该再在此socket上读数据了!

|
从TCP来说,
两端中任何一端如果要断开连接,
都应当友好的发送一个shutdown给对方
然后再退出
对端如果收到shutdown自然也会退出,如果收不到那也没有办法

也就是说,没有可靠的办法保证连接两端可以友好可靠的退出

心跳检测是应用上一个不错的办法!
很多实际的业务中都是采用了心跳的方式。(在实时性要求不高的情况下)

    
 
 

您可能感兴趣的文章:

  • 请教:关于[linux/unix环境下连接到Oracle数据库后断开连接]的问题
  • linux 有线连接了却显示有线连接断开是怎么回事
  • Linux下的Socket通信如何断开连接的端口从而实现重复使用该端口
  • linux下,如何检测网络线连接或断开?
  • 用vnc链接linux远程桌面登录后立刻断开
  • linux下 终端 如何断开连接在一个端口上的设备
  • linux端是服务器,客户端连接后,有时并不知道客户端断开,怎么侦测?
  • 请问linux下Server端程序怎么检测到Client拔掉网线的情况?好像收不到连接断开或错误事件!
  • 在linux下面,为什么TCP服务器端在客户端没有断开前推出程序会关不掉socket?
  • 编一个程序,检测Linux系统下机器网卡的状态(只要检测网络线是否被拔掉?)
  • 如何让linux重启时自动检测文件系统!??
  • linux怎么加检测超时程序!!!
  • linux7.2网卡检测不到
  • linux启动时,能否跳过硬盘检测。
  • 在Linux下如何检测IP地址冲突,及网线脱落
  • linux怎么无法检测到我的键盘和鼠标?
  • 求助关于LINUX下检测不到网卡的问题。
  • linux下如何检测鼠标移动了。
  • 请教一个关于linux下检测fstream失效的问题
  • 如何 linux下检测 usb摄像头(或设备)热插拔事件
  • linux声音问题!可以检测到声卡型号但没声音!在线等待!
  • linux 硬件检测,驱动自动加载的问题
  • ********菜鸟问题,LINUX安装时没有检测到网卡*********
  • RedHat Linux下怎样检测新硬件?
  • linux程序中如何检测机器所用的硬件
  • 为什么我下载的RedHat Linux 被检测未知的操纵系统???
  • linux下如何检测网络状态
  • linux控制台程序如何检测有无按键?
  • rd linux9.0启动的时候,不检测光驱如何实现
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • SSL握手通信详解及linux下c/c++ SSL Socket代码举例
  • 大家帮忙推荐一本linux socket编程的入门书,我刚接触socket,谢谢!!
  • Linux c socket编程:简单的客户端(client)和服务端(server)实现
  • linux socket programe 同一个IP下 bind 多个socket,可以不??
  • linux socket问题。。怎样获得已帮定特定port的一个套接字socket
  • ★★★LINUX与windows的网络编程socket有多大区别?
  • linux下socket编程问题!
  • Linux 下用什么函数查找socket上一次的错误?
  • 求助!!linux下socket编程
  • 请问,在linux下如何探测socket端口通不通啊?
  • 关于LINUX内部socket
  • linux socket fd 写阻塞问题
  • linux下用socket实现多进程间通信问题?
  • 请教: linux下用c++写最简单的socket程序如何写?
  • 问个linux下raw socket的问题
  • 想搞linux下的socket编程,请大家给些意见^_^
  • 如何清楚linux系统中以退出程序的socket连接?
  • 急!!请教关于linux socket编程的一个问题!!
  • 哪里有linux下的c++的socket库????
  • windows 与 linux socket 编程问题
  • 在linux下,我的socket为什么小于零?
  • linux c/c++ IP字符串转换成可比较大小的数字
  • 在win分区上安装linux和独立分区安装linux有什么区别?可以同时安装吗?(两个linux系统)
  • linux哪个版本好?linux操作系统版本详细介绍及选择方案推荐
  • 在虚拟机上安装的linux上,能像真的linux系统一样开发linux程序么?
  • secureCRT下Linux终端汉字乱码解决方法
  • 我重装window后,把linux的引导区覆盖了,进不了linux怎么办?急啊,望热心的人帮助 (现在有linux的盘)
  • Linux c字符串中不可打印字符转换成16进制
  • 安装vmware软件,不用再安装linux系统,就可以模拟linux系统了,然后可以在其上学习一下LINUX下的基本操作 了?
  • Linux常用命令介绍:更改所属用户群组或档案属性
  • 红旗Linux主机可以通过127.0.0.1访问,但如何是连网的Win2000机器通过Linux的IP去访问Linux


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3