由select/epoll返回的非阻塞connect还会是EINPROGRESS状态吗?

一般情况下,我们像下面代码中所示的这样使用非阻塞connect:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <unistd.h>

#include <fcntl.h>

#include <arpa/inet.h>

#include <sys/epoll.h>

#include <errno.h>

#define EPOLL_MAXEVENTS 64

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

{

    int
fd, epfd, flags, status, ret, nevents, i, slen;

    struct
sockaddr_in addr;

    struct
in_addr remote_ip;

    struct
epoll_event ev, events[EPOLL_MAXEVENTS];;

    if
((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {

        perror("socket failed");

        return
-1;

    }

    status = 1;

    if
(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &status, sizeof(int))) {

        perror("setsockopt failed");

        return
-1;

    }

   flags = fcntl(fd, F_GETFL, 0);

    fcntl(fd, F_SETFL, flags | O_NONBLOCK);

    memset(&addr, 0, sizeof(addr));

    addr.sin_family = AF_INET;

    addr.sin_port = 9999;

    if
(inet_pton(AF_INET, "10.232.129.43", &addr.sin_addr) <= 0) {

        perror("inet_pton error");

        return
-1;

    }

    ret = connect(fd, (struct
sockaddr *) &addr, sizeof(struct
sockaddr));

    if
(ret == 0) {

        printf("non-blocking connect success. connect complete immediately");

        close(fd);

        return
-1;

    }

    if
(ret < 0 && errno
!= EINPROGRESS) {

        perror("connect error!");

        return
-1;

    }

    epfd = epoll_create(EPOLL_MAXEVENTS);

 ev.events = EPOLLOUT;

    ev.data.fd = fd;

    if
(epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) == -1 ) {

        perror("epoll_ctl error");

        goto
finish;

    }

    printf("add connect fd into epoll");

    memset(events, 0, sizeof(events));

    for
(;;) {

        nevents = epoll_wait(epfd, events, EPOLL_MAXEVENTS, -1);

        if
(nevents < 0) {

            perror("epoll_wait failed");

            goto
finish;

        }

        for
(i = 0; i < nevents; i++) {

            if
(events[i].data.fd == fd) {

                if
(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void
*) &status, &slen)

                    < 0)

                {

                    perror("getsockopt error!");

                    goto
finish;

                }

                if
(status != 0) {

                    perror("connect error!");

                    goto
finish;

                }

                printf("non-blocking connect success!");

                if
(epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) == -1 ) {

                    perror("epoll_ctl error");

                    return
0;

                }

                /* DO write... */

            }

        }

    }

 finish:

    close(fd);

    close(epfd);

    return
0;

}

  在上面的代码中需要注意几点:

1,什么时候connect返回成功?

三次握手中的client如果收到server对SYN的ACK,connect就会返回。

2,非阻塞的connect成功返回后,用getsockopt获得的SO_ERROR码还会使EINPROGRESS吗?

不会。除非是epoll设置的超时时间到达,否则epoll_wait返回fd后,表明fd已经可写,connect已经建立成功。此时如果getsockopt获取到的SO_ERROR
状态码是status表明connect已失败,不可能再是EINPROGRESS。

时间: 2025-01-20 04:12:21

由select/epoll返回的非阻塞connect还会是EINPROGRESS状态吗?的相关文章

(转)非阻塞Connect对于select时应注意问题

对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后必须调用bind绑定到一个指定的地址,然后调用int listen(int sockfd, int backlog);进行监听.此时服务器socket允许客户端进行连接,backlog提示没被accept的客户连接请求队列的大小,系统决定实际的值,最大值定义为SOMAXCONN在头文件<sys/so

时间获取程序客户端 TCP 使用非阻塞connect

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie /** * TCP,使用非阻塞 connect **/ #include "unp.h" int connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec) { int flags, n, error; socklen_t len; fd_set rset, wset; struct timeval t

非阻塞connect

步骤1: 设置非阻塞,启动连接 实现非阻塞 connect ,首先把 sockfd 设置成非阻塞的.这样调用 connect 可以立刻返回,根据返回值和 errno 处理三种情况: (1) 如果返回 0,表示 connect 成功. (2) 如果返回值小于 0, errno 为 EINPROGRESS, 表示连接 建立已经启动但是尚未完成.这是期望的结果,不是真正的错误. (3) 如果返回值小于0,errno 不是 EINPROGRESS,则连接出错了. 步骤2:判断可读和可写 然后把 sock

面向连接的socket数据处理过程以及非阻塞connect问题

对于面向连接的socket类型(SOCK_STREAM,SOCK_SEQPACKET)在读写数据之前必须建立连接,首先服务器端socket必须在一个客户端知道的地址进行监听,也就是创建socket之后必须调用bind绑定到一个指定的地址,然后调用int listen(int sockfd, int backlog);进行监听.此时服务器socket允许客户端进行连接,backlog提示没被accept的客户连接请求队列的大小,系统决定实际的值,最大值定义为SOMAXCONN在头文件<sys/so

linux 非阻塞 connect函数

开发测试环境:虚拟机CentOS,windows网络调试助手        非阻塞模式有3种用途        1.三次握手同时做其他的处理.connect要花一个往返时间完成,从几毫秒的局域网到几百毫秒或几秒的广域网.这段时间可能有一些其他的处理要执行,比如数据准备,预处理等.        2.用这种技术建立多个连接.这在web浏览器中很普遍.        3.由于程序用select等待连接完成,可以设置一个select等待时间限制,从而缩短connect超时时间.多数实现中,connec

TCP非阻塞accept和非阻塞connect

http://blog.chinaunix.net/uid-20751538-id-238260.html 非阻塞accept 当一个已完成的连接准备好被accept的时候,select会把监听socket标记为可读.因此,如果用select等待外来的连接时,应该不需要 把监听socket设置为非阻塞模式,因为如果select告诉我们连接已经就绪,accept就不应该被阻塞.不过这样做的时候有一个BUG:当客户端 在跟服务器建立连接之后发送了一个RST包,这个时候accept就会阻塞,直到有下一

TCP之非阻塞connect和accept

套接字的默认状态是阻塞的,这就意味着当发出一个不能立即完成的套接字调用时,其进程将被投入睡眠,等待响应操作完成,可能阻塞的套接字调用可分为以下四类: (1) 输入操作,包括read,readv,recv,recvfrom,recvmsg: (2) 输出操作,包括write,writev,send,sendto,sendmsg: (3) 接受外来连接,即accept函数. (4) 发起外出连接,即tcp的connect函数: 非阻塞connect: 当一个非阻塞的tcp套接字上调用connect时

UNIX网络编程-非阻塞connect和非阻塞accept

1.非阻塞connect 在看了很多资料之后,我自己的理解是:在socket发起一次连接的时候,这个过程需要一段时间来将三次握手的过程走完,如果在网络状况不好或者是其他的一些情况下,这个过程需要比较长的时间,我们在连接之前将socket设置为非阻塞模式之后,调用connect函数之后,立即返回,如果成功返回0,如果不成功则返回EINPROGRESS,这个值表明连接正在进行,我们可以设置一个超时时间,然后在这个时间段内不停的检查socket是否连接上了,如果在这个时间段内还没有连上,则返回失败.在

非阻塞connect的作用及代码示例

connect 函数的调用涉及到TCP连接的三次握手过程,通常阻塞的connect 函数会等待三次握手成功或失败后返回,0成功,-1失败.如果对方未响应,要隔6s,重发尝试,可能要等待75s的尝试并最终返回超时,才得知连接失败.即使是一次尝试成功,也会等待几毫秒到几秒的时间,如果此期间有其他事务要处理,则会白白浪费时间,而用非阻塞的connect 则可以做到并行,提高效率. 而通常,非阻塞的connect 函数与 select 函数配合使用:在一个TCP套接口被设置为非阻塞之后调用connect