`
kenby
  • 浏览: 724598 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

非阻塞connect的实现

 
阅读更多

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

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

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

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

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

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

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

 

步骤2:判断可读和可写

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

是否可写,处理三种情况:

(1) 如果连接建立好了,对方没有数据到达,那么 sockfd 是可写的

(2) 如果在 select 之前,连接就建立好了,而且对方的数据已到达,

      那么 sockfd 是可读和可写的。

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

判断 connect 是否成功,就得区别 (2) 和 (3),这两种情况下 sockfd 都是

可读和可写的,区分的方法是,调用 getsockopt 检查是否出错。

 

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

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

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

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

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

返回错误,getsockopt 本身返回0;然而 Solaris 却让 getsockopt 返回 -1,

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

这两种情况。

 

代码:

 

int conn_nonb(int sockfd, const struct sockaddr_in *saptr, socklen_t salen, int nsec)
{
    int flags, n, error, code;
    socklen_t len;
    fd_set wset;
    struct timeval tval;

    flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

    error = 0;
    if ((n == connect(sockfd, saptr, salen)) == 0) {
        goto done;
    } else if (n < 0 && errno != EINPROGRESS){
        return (-1);
    }

    /* Do whatever we want while the connect is taking place */

    FD_ZERO(&wset);
    FD_SET(sockfd, &wset);
    tval.tv_sec = nsec;
    tval.tv_usec = 0;

    if ((n = select(sockfd+1, NULL, &wset, 
                    NULL, nsec ? &tval : NULL)) == 0) {
        close(sockfd);  /* timeout */
        errno = ETIMEDOUT;
        return (-1);
    }

    if (FD_ISSET(sockfd, &wset)) {
        len = sizeof(error);
        code = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);
        /* 如果发生错误,Solaris实现的getsockopt返回-1,
         * 把pending error设置给errno. Berkeley实现的
         * getsockopt返回0, pending error返回给error. 
         * 我们需要处理这两种情况 */
        if (code < 0 || error) {
            close(sockfd);
            if (error) 
                errno = error;
            return (-1);
        }
    } else {
        fprintf(stderr, "select error: sockfd not set");
        exit(0);
    }

done:
    fcntl(sockfd, F_SETFL, flags);  /* restore file status flags */
    return (0);
}
分享到:
评论

相关推荐

    linux客户端Socket非阻塞connect编程[归纳].pdf

    本文档详细介绍了 Linux 客户端 Socket 非阻塞 connect 编程的实现方法和原理。非阻塞 connect 是一种高效的网络编程技术,能够提高程序的性能和可靠性。 一、非阻塞 connect 的应用场景 非阻塞 connect 主要应用...

    linux客户端Socket非阻塞connect编程收集.pdf

    本文档主要讨论了 Linux 客户端 Socket 非阻塞 connect 编程的实现与应用,非阻塞 connect 编程的主要用途有三种: 1. 三次握手同时做其他的处理。在 connect 过程中,可以执行其他的处理,如数据准备、预处理等。 ...

    非阻塞connect,select超时

    网络实现非阻塞connect,select带超时

    非阻塞TCP,VC2010,更新版

    1. `tcp_unblocked_client_1`:可能是第一个非阻塞TCP客户端的实现,可能展示了基础的非阻塞套接字创建和使用。 2. `tcp_unblocked_server`:这是服务器端的实现,它可能使用IOCP或者其他多路复用技术来处理来自多个...

    C++ TCP客户端非阻塞连接超时测试源码

    在C++中,可以使用`select()`、`poll()`或`epoll()`等系统调用来实现非阻塞I/O操作。 在TCP连接过程中,如果服务器端不存在或者未启动,客户端的连接请求会一直等待,直到超时。为了避免这种情况,我们需要实现连接...

    QTcpSocket通信编程时阻塞与非阻塞的问题 - findumars - 博客园1

    在QTcpSocket的编程中,我们经常会遇到阻塞和非阻塞两种模式的选择。这两种模式在处理网络通信时有着不同的行为和应用场景。 首先,阻塞模式意味着在执行某些操作(如连接、读取或写入数据)时,QTcpSocket会暂停...

    Linux下的Socket编程实例(阻塞和非阻塞)

    Linux下的Socket编程实例(阻塞和非阻塞) 通过分析给定的文件信息,我们可以生成以下知识点: Socket编程概述 Socket 编程是指使用操作系统提供的 socket 编程接口来实现网络通信的编程方式。Socket 编程可以实现...

    非阻塞tcpip通讯

    2. **套接字选项SO_OOBINLINE和SO_NONBLOCK**:设置套接字为非阻塞模式通常通过设置套接字选项SO_NONBLOCK实现。这允许在没有数据可读时,recv调用返回错误而不是阻塞。同时,如果希望接收带外数据(OOB,Out-of-...

    Linux非阻塞套接字client

    在Linux系统中,非阻塞套接字...在提供的"client"文件中,可能包含了具体的客户端代码示例,展示了如何在Linux环境下实现非阻塞套接字的客户端。通过分析和学习这个代码,你可以深入理解非阻塞套接字编程的实践方法。

    IO中同步、异步与阻塞、非阻塞的区别

    在软件开发领域,尤其是在涉及输入输出(IO)操作时,理解同步与异步、阻塞与非阻塞的概念是非常重要的。这些概念对于设计和实现高效的程序至关重要,尤其是在高并发和分布式系统中。 一、同步与异步 同步和异步是...

    python多线程非阻塞socket

    本文将深入探讨如何在Python中实现多线程非阻塞的Socket服务端和客户端,以提升并发处理能力。 首先,让我们理解“多线程”和“非阻塞”的概念。多线程是指在一个进程中同时执行多个线程,每个线程独立完成特定任务...

    使用OTP原理构建一个非阻塞的TCP服务器

    在本文中,我们将探讨如何使用Erlang的OTP(Open Telecom Platform)原则构建一个非阻塞的TCP服务器。OTP为开发健壮、容错的应用提供了强大的框架,它包含了一系列行为模式,如gen_server和gen_fsm,这些模式可以...

    Java NIO非阻塞服务端与客户端相互通信

    - **连接操作**:非阻塞模式下,connect()方法如果连接未完成,会立即返回,需要通过选择器监控连接状态。 4. **读写操作** - **read()和write()**:这两个方法在非阻塞模式下,如果缓冲区无数据可读或无空间可写...

    非阻塞java通信代码

    在Java中实现非阻塞通信,主要依赖于Java NIO(Non-blocking Input/Output)库。 1. Java NIO简介: Java NIO是Java 1.4引入的新I/O API,是对传统BIO(Blocking I/O)模型的补充。NIO的核心概念包括通道(Channel...

    VC2010,非阻塞TCP简单源码

    本篇将深入讲解基于VC2010环境下的非阻塞TCP(Transmission Control Protocol)网络编程。非阻塞模式允许程序在等待数据到来时,不被阻塞并可以执行其他任务,从而提高系统的效率和响应性。 首先,我们要理解TCP的...

    阻塞及非阻塞通信

    阻塞与非阻塞通信是计算机网络编程中的两种基本通信方式,主要涉及到Java NIO(Non-blocking Input/Output,非阻塞输入/输出)框架。Java NIO 提供了一种新的方式来处理I/O操作,使得程序在进行读写操作时,不再必须...

    非阻塞异步传输java网络编程(含源代码)

    本实验通过Java实现了基于自定义协议的非阻塞异步文件传输系统,不仅加深了对非阻塞IO的理解,还学会了如何使用SocketChannel和FileChannel进行网络通信及文件操作。此外,通过选择器的选择机制,实现了高效的并发...

    从linux源码看socket的阻塞和非阻塞1

    以一个简单的非阻塞TCP客户端为例,它创建一个Socket并设置为非阻塞模式,然后通过`connect()`函数发起连接请求。在非阻塞模式下,`recv()`函数可能在连接尚未完全建立或没有数据可接收时返回EAGAIN或EWOULDBLOCK...

    异步非阻塞socket聊天室程序

    "异步非阻塞socket聊天室程序"是一个使用C++语言,并基于MFC(Microsoft Foundation Classes)库构建的项目,旨在实现高效的多用户通信。下面将详细阐述这个程序背后的关键知识点。 首先,我们关注的是"异步非阻塞...

    Qt模式弹框不阻塞

    总之,“Qt模式弹框不阻塞”是一种利用透明顶层窗口实现的非阻塞式交互方式,它结合了模态对话框的视觉焦点和非模态窗口的可操作性,为用户界面设计提供了更多的灵活性。在Qt编程中,通过设置窗口属性和旗标,我们...

Global site tag (gtag.js) - Google Analytics