<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    linux下判斷網絡是否連接

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    本文改寫自網上的一個程序,原始程序中為阻塞式調用,而且有現成創建的過程,非常不利于集成到自己程序中,因此對原始程序進行改造,使其可以完成發送一個imcp包的方式來判斷網絡連通,只需要調用改進后的

     bool NetIsOK()

    函數即可,該函數返回true即表示網絡狀態良好,否則表示網絡狀態不連同,本程序中只發送了一個icmp包,在實際應用中可以根據需要改進為發送多個imcp包。修改之后的程序為:只需要調用函數NetIsOK()即可。源碼如下所示:

     

    #include <stdio.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <netinet/ip_icmp.h>
    #include <netdb.h>
    #include <errno.h>
    #define MAX_WAIT_TIME 1
    #define MAX_NO_PACKETS 1
    #define ICMP_HEADSIZE 8
    #define PACKET_SIZE 4096
    struct timeval tvsend,tvrecv;
    struct sockaddr_in dest_addr,recv_addr;
    int sockfd;
    pid_t pid;
    char sendpacket[PACKET_SIZE];
    char recvpacket[PACKET_SIZE];

    //函數定義
    void timeout(int signo);
    unsigned short cal_chksum(unsigned short *addr,int len);
    int pack(int pkt_no,char *sendpacket);
    int send_packet(int pkt_no,char *sendpacket);
    int recv_packet(int pkt_no,char *recvpacket);
    int unpack(int cur_seq,char *buf,int len);
    void tv_sub(struct timeval *out,struct timeval *in);
    void _CloseSocket();

    bool NetIsOk()
    {

    double rtt;
    struct hostent *host;
    struct protoent *protocol;
    int i,recv_status;

    #ifdef _USE_DNS //如果定義該宏,則可以使用域名進行判斷網絡連接,例如www.baidu.com
    /* 設置目的地址信息 */
    char hostname[32];
    sprintf(hostname,"%s","www.baidu.com")
    bzero(&dest_addr, sizeof(dest_addr));
    dest_addr.sin_family = AF_INET;

    if((host=gethostbyname(hostname))==NULL)
    {
    printf("[NetStatus] error : Can't get serverhost info!\n");
    return false;
    }

    bcopy((char*)host->h_addr,(char*)&dest_addr.sin_addr,host->h_length);
    #else //如果不使用域名,則只能用ip地址直接發送icmp包,例如谷歌的地址:8.8.8.8
    dest_addr.sin_addr.s_addr = inet_addr("8.8.8.8");
    #endif


    if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
    { /* 創建原始ICMP套接字 */
    printf("[NetStatus] error : socket");
    return false;
    }

    int iFlag;
    if(iFlag = fcntl(sockfd,F_GETFL,0)<0)
    {
    printf("[NetStatus] error : fcntl(sockfd,F_GETFL,0)");
    _CloseSocket();
    return false;
    }
    iFlag |= O_NONBLOCK;
    if(iFlag = fcntl(sockfd,F_SETFL,iFlag)<0)
    {
    printf("[NetStatus] error : fcntl(sockfd,F_SETFL,iFlag )");
    _CloseSocket();
    return false;
    }

    pid=getpid();
    for(i=0;i<MAX_NO_PACKETS;i++)
    {

    if(send_packet(i,sendpacket)<0)
    {
    printf("[NetStatus] error : send_packet");
    _CloseSocket();
    return false;
    }

    if(recv_packet(i,recvpacket)>0)
    {
    _CloseSocket();
    return true;
    }

    }
    _CloseSocket();
    return false;
    }



    int send_packet(int pkt_no,char *sendpacket)
    {
    int packetsize;
    packetsize=pack(pkt_no,sendpacket);
    gettimeofday(&tvsend,NULL);
    if(sendto(sockfd,sendpacket,packetsize,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr))<0)
    {
    printf("[NetStatus] error : sendto error");
    return-1;
    }
    return1;
    }


    int pack(int pkt_no,char*sendpacket)
    {
    int i,packsize;
    struct icmp *icmp;
    struct timeval *tval;
    icmp=(struct icmp*)sendpacket;
    icmp->icmp_type=ICMP_ECHO;//設置類型為ICMP請求報文
    icmp->icmp_code=0;
    icmp->icmp_cksum=0;
    icmp->icmp_seq=pkt_no;
    icmp->icmp_id=pid;//設置當前進程ID為ICMP標示符
    packsize=ICMP_HEADSIZE+sizeof(struct timeval);
    tval=(struct timeval *)icmp->icmp_data;
    gettimeofday(tval,NULL);
    icmp->icmp_cksum=cal_chksum((unsignedshort*)icmp,packsize);
    return packsize;
    }


    unsignedshort cal_chksum(unsignedshort*addr,int len)
    {
    int nleft=len;
    int sum=0;
    unsignedshort*w=addr;
    unsignedshort answer=0;
    while(nleft>1)//把ICMP報頭二進制數據以2字節為單位累加起來
    {
    sum+=*w++;
    nleft-=2;
    }
    if( nleft==1)//若ICMP報頭為奇數個字節,會剩下最后一字節.把最后一個字節視為一個2字節數據的高字節,這個2字節數據的低字節為0,繼續累加
    {
    *(unsignedchar*)(&answer)=*(unsignedchar*)w;
    sum+=answer;
    }
    sum=(sum>>16)+(sum&0xffff);
    sum+=(sum>>16);
    answer=~sum;
    return answer;
    }


    int recv_packet(int pkt_no,char*recvpacket)
    {
    int n,fromlen;
    fd_set rfds;
    FD_ZERO(&rfds);
    FD_SET(sockfd,&rfds);
    signal(SIGALRM,timeout);
    fromlen=sizeof(recv_addr);
    alarm(MAX_WAIT_TIME);
    while(1)
    {
    select(sockfd+1,&rfds, NULL, NULL, NULL);
    if(FD_ISSET(sockfd,&rfds))
    {
    if((n=recvfrom(sockfd,recvpacket,PACKET_SIZE,0,(struct sockaddr *)&recv_addr,&fromlen))<0)
    {
    if(errno==EINTR)
    return-1;
    perror("recvfrom error");
    return-2;
    }
    }
    gettimeofday(&tvrecv,NULL);
    if(unpack(pkt_no,recvpacket,n)==-1)
    continue;
    return1;
    }
    }

    int unpack(int cur_seq,char*buf,int len)
    {
    int iphdrlen;
    struct ip *ip;
    struct icmp *icmp;
    ip=(struct ip *)buf;
    iphdrlen=ip->ip_hl<<2;//求ip報頭長度,即ip報頭的長度標志乘4
    icmp=(struct icmp *)(buf+iphdrlen);//越過ip報頭,指向ICMP報頭
    len-=iphdrlen;//ICMP報頭及ICMP數據報的總長度
    if( len<8)
    return-1;
    if((icmp->icmp_type==ICMP_ECHOREPLY)&&(icmp->icmp_id==pid)&&(icmp->icmp_seq==cur_seq))
    return0;
    elsereturn-1;
    }


    void timeout(int signo)
    {
    printf("Request Timed Out\n");
    }

    void tv_sub(struct timeval *out,struct timeval *in)
    {
    if((out->tv_usec-=in->tv_usec)<0)
    {
    --out->tv_sec;
    out->tv_usec+=1000000;
    }
    out->tv_sec-=in->tv_sec;
    }

    void_CloseSocket()
    {
    close(sockfd);
    sockfd =0;
    }

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全