检测网络连接状态_转

1. 根据ifconfig中相应网口的RUNNING字段检查

int check_net(const char *eth)
{
    int ret = 1;
    char buf[256];
    FILE *fp;
    memset(buf, 0, 256);

    sprintf(buf, "ifconfig %s | grep ‘RUNNING‘", eth);
    fp = popen(buf, "r");
    if(fp == NULL)
    {
        kprintf(KRELEASE, E_DUMMY, "failed to popen %s\n", buf);
        return 0;
    }

    memset(buf, 0, 256);
    fgets(buf, 256, fp);

    if(!strcmp(buf, ""))
        ret = 0;
    else
        ret = 1;

    pclose(fp);

}

2. 心跳包

void try_connect_tcp(void)
{
    int ret;
    int opt = 1;
    int keep_intvl = 5;
    int keep_probes= 3;
    int keep_idletime = 5;
    int sd = 0;

    sd = socket(AF_INET, SOCK_STREAM, 0);
    if(sd < 0)
    {
        printf("failed to create socket(tcp)\n");
        return;
    }

    setsockopt(sd,SOL_SOCKET,SO_KEEPALIVE,&opt,sizeof(opt));
    setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    setsockopt(sd,SOL_TCP,TCP_KEEPCNT,&keep_probes,sizeof(int));
    setsockopt(sd,SOL_TCP,TCP_KEEPINTVL,&keep_intvl,sizeof(int));
    setsockopt(sd,SOL_TCP,TCP_KEEPIDLE,&keep_idletime,sizeof(int));

    fcntl(sd, F_SETFL, O_NONBLOCK | fcntl(sd, F_GETFL));

    connect(sd, (struct sockaddr *)addr, sizeof(struct sockaddr_in));

    ret = check_tcp_connect(sd, gtimeout);
    if(ret == 1)//connect success
    {
        printf("Tcp(%d) connect success!!!\n", which);
     }
    else//connect failed
    {
        close(sd);
        printf("Connect to sd failed!\n");
    }

}

转自:http://blog.csdn.net/rainharder/article/details/47022903

TCP的keep-alive可以在不增加服务器处理逻辑的前提下,检测客户端连接是否中断

/proc/sys/net/ipv4/tcp_keepalive_time 开始首次KeepAlive探测前的TCP空闭时间 
/proc/sys/net/ipv4/tcp_keepalive_intvl 两次KeepAlive探测间的时间间隔 
/proc/sys/net/ipv4/tcp_keepalive_probes 判定断开前的KeepAlive探测次数

对 于一个已经建立的tcp连接。如果在keepalive_time时间内双方没有任何的数据包传输,则开启keepalive功能的一端将发送 keepalive数据包,若没有收到应答,则每隔keepalive_intvl时间再发送该数据包,发送keepalive_probes次。一直没有 收到应答,则发送rst包关闭连接。若收到应答,则将计时器清零。

谁想定期检查连接状况,谁就启用keep alive。另一端可以不起,只是被动地对探测包进行响应,这种响应是tcp协议的基本要求,跟keep alive无关。并不需要客户端和服务器端都开启keep alive。

Remember that keepalive support, even if configured in the kernel, is not the default behavior in Linux. Programs must request keepalive control for their sockets using the setsockopt interface.

虽然是全局配置,但想要生效,还得程序各自开启

int keepalive = 1; // 开启keepalive属性
int keepidle = 60; // 如该连接在60秒内没有任何数据往来,则进行探测
int keepinterval = 5; // 探测时发包的时间间隔为5 秒
int keepcount = 3; // 探测尝试的次数。如果第1次探测包就收到响应了,则后2次的不再发。
setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive , sizeof(keepalive));
// 可配置各socket自己的keepalive参数
setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, (void*)&keepidle , sizeof(keepidle));
setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepinterval , sizeof(keepinterval));
setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void *)&keepcount , sizeof(keepcount));

Remember that keepalive is not program-related, but socket-related, so if you have multiple sockets, you can handle keepalive for each of them separately.

从上面的接口也可以看出,keepalive设置是socket相关的。 
另外这些属性是sockt继承的,即listen的套接字设置该属性后,后面建立连接后的accept 套接字同样继承该属性(心跳属性)。

import socket

HOST = ‘‘                 # Symbolic name meaning all available interfaces
PORT = 50007              # Arbitrary non-privileged port
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
s.setsockopt(socket.SOL_TCP, socket.SO_KEEPIDEL, 10)
s.setsockopt(socket.SOL_TCP, socket.SO_KEEPINTVL, 3)
s.setsockopt(socket.SOL_TCP, socket.SO_KEEPCNT, 2)

conn, addr = s.accept()
print ‘Connected by‘, addr
while 1:
    data = conn.recv(1024)
    if not data: break
    conn.sendall(data)
conn.close()

但是,tcp自己的keepalive有这样的一个bug:

正常情况下,连接的另一端主动调用colse关闭连接,tcp会通知,我们知道了该连接已经关闭。但是如果tcp连接的另一端突然掉线,或者重启断电,这个时候我们并不知道网络已经关闭。而此时,如果有发送数据失败,tcp会自动进行重传。重传包的优先级高于keepalive,那就意味着,我们的keepalive总是不能发送出去。 而此时,我们也并不知道该连接已经出错而中断。在较长时间的重传失败之后,我们才会知道。

参考

http://www.tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/ 
http://blog.csdn.net/ctthuangcheng/article/details/8596818 
http://blog.csdn.net/ctthuangcheng/article/details/9450087

时间: 2024-08-08 01:28:30

检测网络连接状态_转的相关文章

android检测网络连接状态示例讲解

网络的时候,并不是每次都能连接到网络,因此在程序启动中需要对网络的状态进行判断,如果没有网络则提醒用户进行设置 Android连接首先,要判断网络状态,需要有相应的权限,下面为权限代码(AndroidManifest.xml): 复制代码 代码如下: <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><uses-permission android:name="a

检测网络连接状态

#import "AFNetworkReachabilityManager.h" - (BOOL)isNetWorkReachable{ __block CGRect rect = _nonNetworkLabel.frame; //这里的声明前面加__block,作用是在块里可以修改rect的值: AFNetworkReachabilityManager *afNetworkReachabilityManager = [AFNetworkReachabilityManager sha

IOS检测网络连接状态(转)

IOS检测网络连接状态(转) 使用之前请从Apple网站下载示例:点此下载 然后将Reachability.h 和 Reachability.m 加到自己的项目中,并引用 SystemConfiguration.framework,就可以使用了. Reachability 中定义了3种网络状态: // the network state of the device for Reachability 1.5. typedef enum { NotReachable = 0, //无连接 Reach

Android 检测网络连接状态

Android APP需要连接网络的时候,并不是每次都能连接到网络,因此需要在程序对当前设备的网络状态进行检测,以便及时对用户进行提醒. 判断网络状态,需要有相应的权限,权限代码如下(AndroidManifest.xml): <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.perm

qt检测网络连接状态【只能检测和路由器的连接,不能测试到外网的连接】

#include <QCoreApplication>#include <QDebug>#include <QTextStream>#include <QDir>#include <QFile>#include <QList>#include <QThread>#include <QtNetwork/QNetworkConfigurationManager>#include <QtNetwork/QNet

[转]:IOS检测网络连接状态

转:http://www.cnblogs.com/ketmales/archive/2013/01/23/2873688.html

Android编程获取网络连接状态(3G/Wifi)及调用网络配置界面

http://www.mobiletuts.me 获取网络连接状态 随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityManager  类,用于网络连接状态的检测. Android开发文档这样描述ConnectivityManager 的作用: Class that answers queries about the state of network connectivi

Android编程 获取网络连接状态 及调用网络配置界面

获取网络连接状态 随着3G和Wifi的推广,越来越多的Android应用程序需要调用网络资源,检测网络连接状态也就成为网络应用程序所必备的功能. Android平台提供了ConnectivityManager 类,用于网络连接状态的检测. Android开发文档这样描述ConnectivityManager的作用: Class that answers queries about the state of network connectivity. It also notifies applic

怎样检查Android网络连接状态

在发送任何HTTP请求前最好检查下网络连接状态,这样可以避免异常.这个教程将会介绍怎样在你的应用中检测网络连接状态. 创建新的项目 1.在Eclipse IDE中创建一个新的项目并把填入必须的信息.  File->New->Android Project 2.创建新项目后的第一步是要在AndroidManifest.xml文件中添加必要的权限. 为了访问网络我们需要 INTERNET 权限 为了检查网络状态我们需要 ACCESS_NETWORK_STATE 权限 AndroidManifest