linux connect nonblock

本文介绍了一个简单的Linux程序,用于检测网络接口(如eth0)的链接状态,通过使用ethtool ioctl命令SIOCETHTOOL。此外,还展示了如何创建非阻塞套接字并使用select进行网络操作。
  1. // Linux下检测网络状态是否正常   
  2.   
  3. #include <sys/types.h>   
  4. #include <string.h>   
  5. #include <stdlib.h>   
  6. #include <sys/ioctl.h>   
  7. #include <stdio.h>   
  8. #include <errno.h>   
  9. #include <net/if.h>   
  10.   
  11.   
  12. struct ethtool_value {  
  13.         __uint32_t      cmd;  
  14.         __uint32_t      data;  
  15. };  
  16.   
  17.   
  18. int main(int argc, char* argv[])  
  19. {  
  20.     struct ethtool_value edata;  
  21.     int fd = -1, err = 0;  
  22.     struct ifreq ifr;  
  23.   
  24.   
  25.         memset(&ifr, 0, sizeof(ifr));  
  26.         strcpy(ifr.ifr_name, "eth0");  
  27.         fd = socket(AF_INET, SOCK_DGRAM, 0);  
  28.         if (fd < 0) {  
  29.                 perror("Cannot get control socket");  
  30.                 return 70;  
  31.         }  
  32.         edata.cmd = 0x0000000a;            //command is Get link status
  33.         ifr.ifr_data = (caddr_t)&edata;  
  34.         err = ioctl(fd, 0x8946, &ifr);             //0X8946是个ioctl命令     
                                                                        //#define SIOCETHTOOL     0x8946     
  35.         if (err == 0) {  
  36.                 fprintf(stdout, "Link detected: %s/n",  
  37.                         edata.data ? "yes":"no");  
  38.         } else if (errno != EOPNOTSUPP) {  
  39.                 perror("Cannot get link status");  
  40.         }  
  41.    return 0;  
  42. }  

 

struct sockaddr_in serv_addr;
serv_addr.sin_family=AF_INET;
serv_addr.sin_port=htons(9999);
serv_addr.sin_addr.s_addr = inet_addr("58.31.231.255"); //inet_addr转换为网络字节序
bzero(&(serv_addr.sin_zero),8);

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

flags = fcntl(sockfd,F_GETFL,0);//获取建立的sockfd的当前状态(非阻塞)
fcntl(sockfd,F_SETFL,flags|O_NONBLOCK);//将当前sockfd设置为非阻塞 

 

    while(1)
    {
        FD_ZERO(&rfds);
        FD_SET(socket_descriptor, &rfds);
        tv.tv_sec = 4;
        tv.tv_usec = 0;
        retval = select(socket_descriptor+1, &rfds, NULL, NULL, &tv);

        if (retval == -1)
            printf("select error\n");
        else if (retval)
        {
            memset(msg_buffer, 0, BUF_SIZE);
            if(FD_ISSET(socket_descriptor, &rfds))
                rlen = recvfrom(socket_descriptor, msg_buffer, BUF_SIZE, 0, (struct sockaddr *)&sin, &sin_len);
            if(rlen > 0)
            {
                printf("recv %s \n", msg_buffer);
            }
            else
            {
                printf("rlen : %d\n", rlen);
            }
        }


 

 

 


 

### Linux `connect` 函数返回值含义及可能的错误代码 在Linux系统中,`connect` 函数用于建立网络连接。其返回值和可能的错误代码具有特定的含义,以下是详细的说明: #### 返回值 - **0**:表示连接成功[^1]。 - **-1**:表示连接失败,此时需要通过 `errno` 来获取具体的错误原因[^3]。 #### 常见错误代码及其含义 以下是一些常见的错误代码以及它们的意义: - **EINPROGRESS**:当套接字处于非阻塞模式时,如果连接尚未完成,`connect` 会立即返回 `-1`,同时将 `errno` 设置为 `EINPROGRESS`[^1]。 - **ECONNREFUSED**:目标主机拒绝了连接请求,通常是因为目标端口上没有监听的服务[^4]。 - **ETIMEDOUT**:连接超时,通常发生在尝试连接远程主机时,目标主机未能及时响应[^3]。 - **ENETUNREACH**:网络不可达,表示无法到达目标网络[^3]。 - **EADDRINUSE**:本地地址已经在使用中,通常是因为绑定的本地地址或端口已被其他进程占用。 - **EAFNOSUPPORT**:地址族不支持,例如尝试使用 IPv6 地址与仅支持 IPv4 的套接字进行连接[^3]。 #### 非阻塞模式下的行为 在非阻塞模式下,`connect` 不会阻塞当前线程,而是立即返回。如果返回值为 `-1` 且 `errno` 为 `EINPROGRESS`,则表示连接正在建立中。可以通过轮询或使用 `select`、`poll` 等函数来检测连接是否完成。 #### 示例代码 以下是一个简单的非阻塞 `connect` 测试代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> int main() { int fd = socket(AF_INET, SOCK_STREAM, 0); if (fd == -1) { perror("socket"); return 1; } // 设置为非阻塞模式 int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); struct sockaddr_in addr = {0}; addr.sin_family = AF_INET; addr.sin_port = htons(80); inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr); while (1) { int ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); if (ret == 0) { printf("Connect success!\n"); break; } else { if (errno != EINPROGRESS) { printf("Connect error! errno: %d\n", errno); break; } else { printf("Connection is being established...\n"); sleep(1); continue; } } } close(fd); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值