Linux socket connect

来源:互联网 发布:文本简繁体转换软件 编辑:程序博客网 时间:2024/05/01 04:14

客户端调用int connect(int sockfd, const struct sockaddr *addr, socklen_t len)发起对服务器的socket的连接请求:

    如果客户端socket描述符为阻塞模式则会一直阻塞到连接建立或者连接失败(注意阻塞模式的超时时间可能为75秒到几分钟之间);

    而如果为非阻塞模式,则调用connect之后如果连接不能马上建立则返回-1(errno设置为EINPROGRESS,注意连接也可能马上建立成功,比如连接本机的服务器进程),如果没有马上建立而返回,此时TCP的三路握手动作在背后继续,而程序可以做其他的东西,然后调用select检测非阻塞connect是否完成(此时可以指定select的超时时间,这个超时时间可以设置为比connect的超时时间短),如果select超时则关闭socket,然后可以尝试创建新的socket重新连接,如果select返回非阻塞socket描述符可写则表明连接建立成功,如果select返回非阻塞socket描述符既可读又可写则表明连接出错(注意:这儿必须跟另外一种连接正常的情况区分开来,就是连接建立好了之后,服务器端发送了数据给客户端,此时select同样会返回非阻塞socket描述符既可读又可写,这时可以通过以下方法区分:

    1.调用getpeername获取对端的socket地址。如果getpeername返回ENOTCONN,表示连接建立失败,然后用SO_ERROR调用getsockopt得到套接口描述符上的待处理错误;

    2.调用read,读取长度为0字节的数据。如果read调用失败,则表示连接建立失败,而且read返回的errno指明了连接失败的原因;如果连接建立成功,read应该返回0;

    3.再调用一次connect。它应该失败,如果错误errno是EISCONN,就表示套接口已经建立,而且第一次连接是成功的;否则连接就是失败的;

    4.直接用SO_ERROR调用getsockopt得到套接口描述符上的待处理错误。如果错误码为0,表示连接成功;否则连接失败。

    对于无连接的socket类型(SOCK_DGRAM),客户端也可以调用connect进行连接,此连接实际上并不建立类似SOCK_STREAM的连接,而仅仅是在本地保存了对端的地址,这样后续的读写操作可以默认以连接的对端为操作对象。