C(LINUX)中的非阻塞客户端套接字
我正在处理一项检查服务器上网络连接可用性的要求(如果网络稳定与否)。我有一个函数,它可以找到在中央服务器上注册的服务器。我通过提取服务器的 URL 和端口号并尝试通过表现得像一个简单的 TCP 客户端来连接到它们,为此功能添加了一层网络检查。如果返回值大于0,则表示网络工作正常;如果-1,则网络损坏。
通过这样的检查,当服务器的网络关闭时,我有时会观察到可变的不一致时间。这种行为的原因在链接中也有道理:时间不一致。
为了解决这个问题,我有一个非阻塞客户端套接字的想法,它尝试连接到服务器。使用这种方法,我观察到的是,每次客户端连接到服务器时,connect() 函数的返回值始终为 -1。
我计划监视 connect() 函数最多 5 秒,如果失败,它应该发送否定响应。
我想要实现的目标:如果服务器可用,连接=0,然后中断它,否则等待 2 秒,如果仍然没有响应,则得出超时结论。
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: %sn", B[i]);
char *p = strrchr(B[i], ':');
int port = strtoul(p+1, NULL, 10);
//printf("%dn",port);
B[i][length-5]=' ';
//printf("Hostname: %sn", B[i]);
//removing the port
A[i][length-5]=' ';
//without initial tcp binding
C[i] = A[i] + 10;
//printf("Hostname: %sn", 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 Foundn");
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 createdn");
memset(&serverAddr,' ',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 : %sn",hostname);
printf("n----Updated Status Information----:n");
printf("Discovery URL : opc.tcp://%s:%dn",hostname,port);
printf("Status:CONNECTON TIMED OUTn");
printf("n");
}
输出:尽管服务器处于活动状态,但显示响应失败
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.
从技术上讲,是否有可能有一个非阻塞客户端,只是有一个连接()函数到一个阻塞服务器?服务器始终在侦听来自客户端的连接。
如果可以实现,这里有关于这种方法的任何指导吗?
问候, 拉克山
回答
您不应该重复该connect操作。只发connect一次。如果它失败了EINPROGRESS,你只需要等待connect成功。你不需要发出另一个connect.
您可以通过多种方式检查连接是否成功。最简单的可能只是使用getpeername. 如果您有对等方,则套接字已连接。您也可以使用select或poll检查套接字是否可写。
如果连接失败并且您想获取错误原因,请尝试read一个字节。它会失败并给你错误代码。你也可以使用getsockopt (fd, SOL_SOCKET, SO_ERROR, ...).
请参阅这篇著名的帖子以获取更少的信息。