美文网首页
connect方法会阻塞,请问有什么方法可以避免其长时间阻塞?

connect方法会阻塞,请问有什么方法可以避免其长时间阻塞?

作者: 只为博军一笑 | 来源:发表于2018-11-12 22:49 被阅读0次

在学习嵌入式Linux网络编程中,很多同学都发现了一个问题,那就是调用connect函数时,如果服务端关闭,客户 端调用connect()函数时,发现阻塞在那里,而且利用ctrl+c信号去停止客户端程序时,需要等待一个较为长的时间才能响应了,这个时间如果大家 细心会发现,每次都是75秒的时间。那么有没有什么比较好的办法,可以以用户能接受的一个时间响应来停止掉一个正在connect连接的客户端那?

---------------------

作者:hj605635529

来源:CSDN

原文:https://blog.csdn.net/hj605635529/article/details/74157305

版权声明:本文为博主原创文章,转载请附上博文链接!

步骤1: 设置非阻塞,启动连接

实现非阻塞 connect ,首先把 sockfd 设置成非阻塞的。这样调用

connect 可以立刻返回,根据返回值和 errno 处理三种情况:

(1) 如果返回 0,表示 connect 成功。

(2) 如果返回值小于 0, errno 为 EINPROGRESS, ?表示连接

? ? ? 建立已经启动但是尚未完成。这是期望的结果,不是真正的错误。

(3) 如果返回值小于0,errno 不是 EINPROGRESS,则连接出错了。

?

步骤2:判断可读和可写

然后把 sockfd 加入 select 的读写监听集合,通过 select 判断 sockfd

是否可写,

(1) 如果连接建立好了,,那么 sockfd 是可写的

(2) 如果连接发生错误,sockfd 也是可读和可写的。

步骤3:使用 getsockopt 函数检查错误

getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &err, &len)

在 sockfd 都是可读和可写的情况下,我们使用 getsockopt 来检查连接

是否出错。但这里有一个可移植性的问题。

如果发生错误,getsockopt 源自 Berkeley 的实现将在变量 err 中

返回错误,getsockopt 本身返回0;(centos是这种错误)

然而 Solaris 却让 getsockopt 返回 -1,

并把错误保存在 errno 变量中。所以在判断是否有错误的时候,要处理

这两种情况。

步骤4:重新将套接字设置为阻塞

#include<stdio.h>

#include<sys/socket.h>

#include<sys/types.h>

#include<arpa/inet.h>

#include<string.h>

#include<netinet/in.h>

#include<string.h>

#include <sys/select.h>

#include<fcntl.h>

/* According to earlier standards */

#include <sys/time.h>

#include <unistd.h>

#include<errno.h>

static void usage(const char *str)

{

printf("Usage:%s,[IP],[PORT]\n",str);

}

int main(int argc ,char *argv[])

{

int sock = socket(AF_INET,SOCK_STREAM,0);

if(sock < 0)

{

perror("sock");

return 1;

}

struct sockaddr_in serv_addr;

serv_addr.sin_family = AF_INET;

serv_addr.sin_port = htons(atoi(argv[2]));

serv_addr.sin_addr.s_addr = inet_addr(argv[1]);

int flag,old_flag;

flag |= O_NONBLOCK;

old_flag = flag = fcntl(sock, F_SETFL, O_NONBLOCK ); //将连接套接字设置为非阻塞。

int ret = connect(sock,(struct sockaddr*)& serv_addr,sizeof(serv_addr));

if(ret != 0)

{

if(errno != EINPROGRESS) //connect返回错误。

{

printf("connect failed\n");

}

//连接正在建立

else

{

struct timeval tm;  //1.定时

tm.tv_sec = 10;

tm.tv_usec = 0;

fd_set wset;

FD_ZERO(&wset);

FD_SET(sock,&wset);

printf("selcet start\n");

int res = select(sock+1, NULL, &wset, NULL, &tm);

printf("select end\n");

if(res <= 0)

{

printf("res <= 0\n");

close(sock);

return 2;

}

if(FD_ISSET(sock,&wset))

{

printf("test \n");

int err = -1;

socklen_t len = sizeof(int);

if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, &len ) < 0) //两种错误处理方式

{

printf("errno :%d %s\n",errno, strerror(errno));

close(sock);

return 3;

}

if(err)

{

printf("connect faile\n");

errno = err;

close(sock);

return 4;

}

printf("connetct success\n");

}

}

}

fcntl(sock, F_SETFL, old_flag); //最后恢复sock的阻塞属性。

char buf[BUFSIZ];

while(1)

{

printf("client say# ");

fflush(stdout);

ssize_t s = read(0,buf,sizeof(buf) - 1);

if(s > 0)

{

buf[s - 1] = 0;

write(sock,buf,strlen(buf));

ssize_t s2 = read(sock,buf,sizeof(buf) -1 );

if(s2 > 0)

{

buf[s2] = 0;

printf("server echo # %s\n",buf);

}

}

}

return 0;

相关文章

  • connect方法会阻塞,请问有什么方法可以避免其长时间阻塞?

    在学习嵌入式Linux网络编程中,很多同学都发现了一个问题,那就是调用connect函数时,如果服务端关闭,客户 ...

  • 非阻塞connect和accept

    1 非阻塞connect 1.1 阻塞模式与非阻塞 调用connect会发起三次连接。 阻塞模式下,connect...

  • iOS中的锁 笔记

    会阻塞线程的锁,都属于互斥锁 NSLock NSLock的lock方法和lockBeforeDate: 方法会阻塞...

  • socket

    socket connect阻塞和非阻塞处理 定义信号处理函数

  • 多线程(15) — 阻塞队列

    阻塞队列(BlockingQueue)接口继承了Queue接口,其有两个实现阻塞的方法:1. 移除阻塞:当队列为空...

  • 网络编程&&多线程编程

    非阻塞模式下,send recv connect、accept函数的情况研究 connect阻塞模式下(超时时间7...

  • LockSupport的用法及原理

    是什么 LockSupport是一个线程阻塞工具类,所有的方法都是静态方法,可以让线程在任意位置阻塞,当然阻塞之后...

  • 一切尽在代码中:一文阐述队列的使用JAVA

    阻塞队列如下: 关于java.util 中提供的队列的方法们: 阻塞队列包括了非阻塞队列中的大部分方法,如上五个方...

  • 避免阻塞

    在实际项目中,对于前端发过来的请求,需要在后端进行长时间的处理,但为了更好的用户体验,让PHP在后端处理时能快速响...

  • netty为啥非阻塞

    netty 的非阻塞 到底是指的什么netty的非阻塞指的是nio多路复用器是阻塞的 其提供 非阻塞调用 阻塞调用...

网友评论

      本文标题:connect方法会阻塞,请问有什么方法可以避免其长时间阻塞?

      本文链接:https://www.haomeiwen.com/subject/sbphfqtx.html