将一个socket 设置成阻塞模式和非阻塞模式,使用fcntl方法,
设置成非阻塞模式:
flags = fcntl(sockfd, F_GETFL, 0); //获取文件的flags值。
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); //设置成非阻塞模式;
设置成阻塞模式:
flags = fcntl(sockfd,F_GETFL,0); //获取文件的flags值。
fcntl(sockfd,F_SETFL,flags&~O_NONBLOCK); //设置成阻塞模式;
在将socket设置成非阻塞模式后,每次的对于sockfd 的操作都是非阻塞的;
非阻塞模式下:
connect
=0 当返回0时,表示立即创建了socket链接,
<0 当返回-1时,需要判断errno是否是EINPROGRESS(表示当前进程正在处理),否则失败。
struct
sockaddr_in serv_addr;
int sockfd=socket(AF_INET, SOCK_STREAM, 0);
int ret =
connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr);
if(ret == 0){}/ /建立链接成功
else if(ret < 0 && errno == EINPROGRESS) //errno == EINPROGRESS表示正在建立链接
{
// 等待连接完成,errno == EINPROGRESS表示正在建立链接
fd_set set;
FD_ZERO(&set);
FD_SET(sockfd,&set);
struct timeval timeo;
timeo.tv_sec = 0;
timeo.tv_usec = 100 * 1000; // 超时时间100ms
int retval = select(sockfd+ 1, NULL, &set, NULL, &timeo); //事件监听
if(retval <= 0) { } //建立链接错误或超时 close(sockfd)
else
{
int error = 0;
socklen_t len = sizeof(error);
if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0 ||
error != 0)
{
//建立链接失败close(sockfd)
}
else
{
//建立链接成功
}
}
}
else{ } //出现错误 close(sockfd)