C ( LINUX ) 中的非阻塞客户端套接字 [英] Non blocking client socket in C ( LINUX)

查看:86
本文介绍了C ( LINUX ) 中的非阻塞客户端套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一项检查服务器上网络连接可用性的要求(如果网络稳定与否).我有一个函数,它可以找到在中央服务器上注册的服务器.我通过提取服务器的 URL 和端口号并尝试通过表现得像一个简单的 TCP 客户端来连接到它们,为此功能添加了一层网络检查.如果返回值大于0,则表示网络工作正常;如果 -1,则网络损坏.

I am working on a requirement which checks the availability of network connection on servers(if network is stable or not). I am having a function, which finds the servers registered at a central server. I am adding a layer of network check over this function by extracting the URL and port number of the servers and trying to connect to them by behaving like a simple TCP client. If the return value is greater than 0, then it means that the network is working fine; if -1, then the network is broken.

通过这样的检查,当服务器的网络关闭时,我有时会观察到变量不一致的时间.链接中也证明了这种行为的原因:时间不一致.

With such a check, I sometimes observe variable inconsistent times when the network of a server is down. The reason for such behavior is also justified in the link : Inconsistent time.

为了解决这个问题,我有一个非阻塞客户端套接字的想法,它尝试连接到服务器.使用这种方法,我观察到的是,每次客户端连接到服务器时,connect() 函数的返回值始终为 -1.

To counter this, I have an idea of having a non blocking client socket, which tries to connect to the server. With this approach, what I observe is, each time, when the client connects to the server, the return value of the connect() function is -1 always.

我计划监控 connect() 函数最多 5 秒,如果失败,它应该发送否定响应.

I plan to monitor to connect() function for maximum of 5 seconds, and if it fails, it should send a negative response.

我想实现的目标:如果服务器可用,连接=0,然后断开它,否则等待2秒,如果仍然没有响应,则得出超时结论.

What I want to achieve: If server is available, connect =0, then break it, else wait for 2seconds, if still not responsive, then conclude as timeout.

printf("--Checking for network connectivity--\n");
        for(size_t i = 0; i < serverOnNetworkSize; i++) {
           UA_ServerOnNetwork *server = &serverOnNetwork[i];
           A[i] = (char *)UA_malloc(server->discoveryUrl.length+1);
           memcpy(A[i],server->discoveryUrl.data,server->discoveryUrl.length);
           A[i][server->discoveryUrl.length] = 0;
           int length = strlen(A[i]);
          
          //discovery URLs are of the form : opc.tcp://hostname:port
          
          //new addition to extract port
            B[i] = A[i] + 10;
          //printf("Hostname: %s\n", B[i]);
            char *p = strrchr(B[i], ':');
            int port = strtoul(p+1, NULL, 10);
          //printf("%d\n",port);
            B[i][length-5]='\0';
          //printf("Hostname: %s\n", B[i]);
         

         
           //removing the port
           A[i][length-5]='\0';
           //without initial tcp binding
           C[i] = A[i] + 10;
          //printf("Hostname: %s\n", C[i]);

          // FIND IP OF THAT HOST
           if(i!=0){
            char ip_address[50];

            find_ip_address(C[i],ip_address);  
            socketCommunication(ip_address,C[i],port);
       }
}
          printf("--Checks done!--\n");

全局函数:

int find_ip_address(char *hostname, char *ip_address)
{
      struct hostent *host_name;
      struct in_addr **ipaddress;
      int count;
      if((host_name = gethostbyname(hostname)) == NULL)
      {
            herror("\nIP Address Not Found\n");
            return 1;
      }
      else
      {
            ipaddress = (struct in_addr **) host_name->h_addr_list;
            for(count = 0; ipaddress[count] != NULL; count++)
            {
                  strcpy(ip_address, inet_ntoa(*ipaddress[count]));
                  return 0;
            }
      }
      return 1;
}
int ret;
void socketCommunication(char *ip_address,char *hostname, int port){
     int clientSocket,ret;
    struct  sockaddr_in serverAddr;
    char buffer[1024];
 
    
    clientSocket = socket(AF_INET,SOCK_STREAM | SOCK_NONBLOCK,0);
    if(clientSocket<0){
        printf("Error in connection \n");
        exit(1);
    }

    //printf("Client socket is created\n");

    memset(&serverAddr,'\0',sizeof(serverAddr));

    serverAddr.sin_port = htons(port);
    serverAddr.sin_family=AF_INET;
    
    serverAddr.sin_addr.s_addr=inet_addr(ip_address);
    //monitoring for 5 seconds
    for(int i =0; i<=5;i++){
        
        ret = connect(clientSocket,(struct sockaddr*)&serverAddr,sizeof(serverAddr));
        //printf("%d ", ret);
    
        sleep(1);
    }
    if(ret<0){
        printf("\nLOOKS LIKE NETWORK CONNECTION HAS FAILED. HAVE A LOOK AT    THE NETWORK CONNECTIVITY at host : %s\n",hostname);
        printf("\n----Updated Status Information----:\n");
        printf("Discovery URL : opc.tcp://%s:%d\n",hostname,port);
        printf("Status:CONNECTON TIMED OUT\n");
        printf("\n");
   }

输出:尽管服务器处于活动状态,但它显示响应失败

Output: Inspite of the servers being active, it shows a failed response

LOOKS LIKE NETWORK CONNECTION HAS FAILED. HAVE A LOOK AT THE NETWORK CONNECTIVITY at host : o755-gksr

----Updated Status Information----:
Discovery URL : opc.tcp://o755-gksr:4840
Status:CONNECTON TIMED OUT

--Checks done!--
Time measured: 6 seconds.

从技术上讲,是否有可能有一个非阻塞客户端,只是有一个连接()函数到一个阻塞服务器?服务器始终在侦听来自客户端的连接.

Technically, is it possible to have a nonblocking client, just to have a connect()function to a blocking server? The server are always listening to connections from client.

如果可以实现,这里有关于这种方法的任何指导吗?

If it can be achieved, any guidance to this approach here?

问候,洛山

推荐答案

您不应该重复 connect 操作.只需发出 connect 一次.如果 EINPROGRESS 失败,你只需要等待 connect 成功.您不需要发出另一个 connect.

You should not be repeating the connect operation. Just issue connect once. If it fails with EINPROGRESS, you just need to wait for the connect to succeed. You don't need to issue another connect.

您可以通过多种方式检查连接是否成功.最简单的方法可能就是使用 getpeername.如果您有对等方,则套接字已连接.您还可以使用 selectpoll 来检查套接字是否可写.

You can check if the connection is successful several ways. The easiest is probably just to use getpeername. If you have a peer, the socket is connected. You can also use select or poll to check if the socket is writable.

如果连接失败而您想知道错误原因,只需尝试读取一个字节即可.它会失败并给你错误代码.您也可以使用 getsockopt (fd, SOL_SOCKET, SO_ERROR, ...).

If the connection failed and you want to get the error reason, just try to read one byte. It will fail and give you the error code. You can also use getsockopt (fd, SOL_SOCKET, SO_ERROR, ...).

请参阅这篇著名帖子以获取更少信息.

See this famous post for less information.

这篇关于C ( LINUX ) 中的非阻塞客户端套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆