`
memorymyann
  • 浏览: 271106 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

22.非阻塞connect

阅读更多

connect非阻塞套接口时候,一般使用在以下几种情况:

 

1.三路握手需要时间,这个要视具体的网络情况而定。当然也有可能失败。在三路握手的时候我们并不需要在原地等待三路握手的完成,可以用这些时间来 完成其它事情,然后当这些事情完成后,再去检测连接是否建立(也就是三路握手是否完成)。

 

2.可以用这种技术来同时建立多个连接。(WEB浏览器中很常用)。

 

3.connect超时需要很长时间才会通知,如果我们认为超过0.1秒以后就算超时(不管它是不是真的超时),这是就可以使用非阻塞式I/O结合 select来完成。

 

当采用非阻塞式I/O来使用connect时候,要判断一个连接是否建立则比较复杂,需要按照以下几个步骤来完成

 

1.即使是使用非阻塞式的connect操作,connect依然可能正确返回,也就是说非阻塞的connect 也有可能三路连接完成后返回,这种情况一般发生在服务器和主机在同一个机器上,所以第一步要判断connect是否正确返回,如果正确返回则请做正确返回 的处理,否则进入步骤2

 

2.设置fd_set,(如果没看明白,请先看select函数介绍),让select函数同时监听套接字的读写2个属性,如果既可读也可写则进入 步骤3,如果可写但不可读进入步骤4.

 

3.如果到达这步,我们需要调用getsockopt进一步判断。这里涉及到一个移植问题,getsockopt如果发生错误, 源自Berkeley的实现会返回0,如果是solaris,则会返回-1。建议是2个都处理(如果看不明白请先看getsockopt函数,套接口选 项)。根据getsockopt通过参数返回的erron的值,如果值为0则表示链接建立完成,如果不为0, 则说明链接建立没有完成。

 

4.如果能到达这里,则说明连接建立完成。

 

最后,即使最后你得出链接没有建立完成,也只是说:可能三路握手的过程还是没有完成。

 

代码:

服务器

#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#define MAXSIZE 100

//如果这样写,最后返回的套接口应该是会进入步骤3,也就是套接口既可读也可写,如果想进入步骤4,就不要想套接口中写入数据
int main(int argc, char ** argu) {
        int listenfd, connfd;
        struct sockaddr_in servaddr;
        char buf[MAXSIZE + 1];
        char buf2[] = "hello world\n";

        listenfd = socket(AF_INET, SOCK_STREAM, 0);
        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(atoi(argu[1]));
        bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
        listen(listenfd, 10);
        for(;;) {
                connfd = accept(listenfd, (struct sockaddr *)NULL, NULL);
                write(connfd, buf2, sizeof(buf2));
                close(connfd);
        }
}

 

客户端

#include "/programe/net/head.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "fcntl.h"
#include "sys/select.h"

#define MAXSIZE 100

int main(int argc, char ** argv) {
        int sockfd, n;
        int my;
        char send_buf[MAXSIZE + 1];
        char recv_buf[MAXSIZE + 1];
        struct sockaddr_in servaddr;
        int error = 0;

        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
                printf("create socket error\n");
                exit(1);
        }

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(atoi(argv[1]));

        if(inet_pton(AF_INET, "192.168.1.235" , &servaddr.sin_addr) < 0) {
                printf("inet_pton error\n");
                exit(1);
        }

        int val = fcntl(sockfd, F_GETFL, 0);
        fcntl(sockfd, F_SETFL, val | O_NONBLOCK); //设置套接口非阻塞

        int connect_flag = connect(sockfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr_in));

        sleep(2); //connect会立即返回,不同于之前的要阻塞到链接完成才会返回,这里可以做你想在等待连接完成的时间想做的事情,我这里只是让进程睡眠了一段时间
        if(connect_flag >= 0) {
                printf("connect success\n"); //即使是非阻塞套接口,connect还是有可能正确返回的,这种情况要处理

                goto done; //不建议使用goto
        }

        fd_set rest, west;
        FD_ZERO(&rest);
        FD_ZERO(&west);
        FD_SET(sockfd, &rest);
        FD_SET(sockfd, &west);
        int maxpd = sockfd + 1;
        int flag = select(maxpd, &rest, &west, NULL, NULL);//监听套接的可读和可写条件
        if(flag < 0) {
                printf("select error\n");//慢系统调用可能会错误返回,这个以前提过
                exit(1);
        }
        if(FD_ISSET(sockfd, &rest) && FD_ISSET(sockfd, &west)) {//如果套接口及可写也可读,需要进一步判断
                socklen_t len = sizeof(error);
                if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
                        exit(1);//获取SO_ERROR属性选项,当然getsockopt也有可能错误返回
                printf("error = %d\n", error);
                if(error != 0) {//如果error不为0, 则表示链接到此没有建立完成
                        printf("connect failed\n");
                        exit(1);
                }

                //如果error为0,则说明链接建立完成
        }
        if(FD_ISSET(sockfd, &west) && !FD_ISSET(sockfd, &rest)) { //如果套接口可写不可读,则链接完成
                printf("connect success\n");
        }
done:
        int recv_buf_len  = read(sockfd, recv_buf, MAXSIZE);
        recv_buf[recv_buf_len] = '\0';
        printf("get message:%s", recv_buf);
        close(sockfd);
        exit(0);
}

 

 

分享到:
评论

相关推荐

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

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

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

    Linux 客户端 Socket 非阻塞 connect 编程收集 本文档主要讨论了 Linux 客户端 Socket 非阻塞 connect 编程的实现与应用,非阻塞 connect 编程的主要用途有三种: 1. 三次握手同时做其他的处理。在 connect 过程中...

    非阻塞connect,select超时

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

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

    总之,"C++ TCP客户端非阻塞连接超时测试源码"是一个实用的示例,它展示了如何在C++中处理TCP连接的非阻塞和超时问题,这对于开发高可用性和高性能的网络应用程序至关重要。通过学习和分析这段代码,开发者可以提升...

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

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

    非阻塞TCP,VC2010,更新版

    非阻塞TCP的一个挑战在于处理连接建立期间的“半连接”状态,此时`connect()`可能返回一个错误,但实际连接可能仍在进行。这被称为EINPROGRESS错误,需要在客户端进行适当的重试或超时处理。 总结起来,非阻塞TCP...

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

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

    非阻塞java通信代码

    非阻塞Java通信是一种高效的网络编程模式,它允许程序在等待数据就绪时继续执行其他任务,而不是简单地挂起,直到数据准备完毕。这种方式提高了系统资源利用率和并发能力,尤其适用于高并发的网络服务。在Java中实现...

    Linux非阻塞套接字client

    在非阻塞模式下,如果连接尚未完成,`connect()`会立即返回错误`EINPROGRESS`。 4. **I/O复用**:使用`select()`、`poll()`或`epoll()`函数监控连接状态,等待连接完成或超时。 5. **发送和接收数据**:使用`send...

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

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

    非阻塞tcpip通讯

    非阻塞TCP/IP通信是一种高效的网络编程模型,它在处理大量并发连接时具有显著优势。在传统的阻塞模式下,一个套接字调用(如recv或send)会一直阻塞,直到有数据可读或发送空间可用。然而,在非阻塞模式下,这些调用...

    _conn_util.rar_connect

    5. **异步编程**:如果`Snd_conn_req`是在异步环境中执行的,那么可能涉及到事件驱动编程、回调函数或者Promise对象,以处理网络操作的非阻塞特性。 6. **多线程或多进程**:在并发环境下,可能需要使用多线程或多...

    python多线程非阻塞socket

    在Python编程中,多线程和非阻塞的Socket技术是构建高效网络应用程序的关键组成部分。本文将深入探讨如何在Python中实现多线程非阻塞的Socket服务端和客户端,以提升并发处理能力。 首先,让我们理解“多线程”和...

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

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

    VC2010,非阻塞TCP简单源码

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

    阻塞及非阻塞通信

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

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

    ### 非阻塞异步传输Java网络编程 #### 实验背景及目标 本实验旨在通过Java语言实现一种基于自定义协议的文件传输系统,包括一个文件传输服务器(FileServer)和一个客户端(FileClient)。该系统的特点在于采用了非...

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

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

    windows下设置socket的connect超时

    通过以上介绍,我们可以看到在Windows环境下设置socket连接超时的主要步骤包括:建立socket、设置非阻塞模式、调用connect、使用select检测socket状态、判断connect结果以及最后将socket恢复为阻塞模式。这些步骤...

Global site tag (gtag.js) - Google Analytics