首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

尝试从套接字读取,但它阻塞了while循环

当从套接字读取数据时,如果使用了一个阻塞式的套接字,那么read操作可能会一直等待直到有数据可读,这就导致了while循环的阻塞。这种情况通常发生在网络通信中,当客户端或服务器端没有及时发送数据时,另一方的read调用就会一直等待。

基础概念

  • 套接字(Socket):是网络通信的基本构建块,允许不同计算机上的应用程序通过互联网相互通信。
  • 阻塞式套接字:在进行读写操作的时候,若使用阻塞式套接字,则操作不再受到其他I/O操作的限制,直到本次读写操作完成为止。

优势与类型

  • 优势:实现简单,易于理解和使用。
  • 类型
    • 阻塞式套接字
    • 非阻塞式套接字
    • 多路复用套接字(如select、poll、epoll)
    • 信号驱动套接字
    • 异步套接字

应用场景

  • 阻塞式套接字:适用于连接稳定,数据传输频繁且可预测的场景。
  • 非阻塞式及多路复用套接字:适用于连接不稳定,需要处理多个连接的场景。

解决阻塞问题的方法

  1. 设置超时:为套接字操作设置一个超时时间,超过这个时间后自动放弃等待。
  2. 设置超时:为套接字操作设置一个超时时间,超过这个时间后自动放弃等待。
  3. 使用非阻塞模式:通过设置套接字为非阻塞模式,使得recv在没有数据可读时立即返回。
  4. 使用非阻塞模式:通过设置套接字为非阻塞模式,使得recv在没有数据可读时立即返回。
  5. 多路复用:使用selectpollepoll等多路复用技术来监控多个套接字的状态,从而避免阻塞。
  6. 多路复用:使用selectpollepoll等多路复用技术来监控多个套接字的状态,从而避免阻塞。

原因分析

  • 数据未发送:对方可能还没有发送数据,或者网络延迟导致数据还未到达。
  • 套接字配置:套接字默认可能是阻塞模式,没有进行非阻塞设置或超时设置。

解决问题的步骤

  1. 确认对方是否已经发送数据。
  2. 检查网络连接是否稳定。
  3. 对套接字进行适当的配置,如设置超时或切换到非阻塞模式。
  4. 考虑使用多路复用技术来提高程序的响应性和效率。

通过上述方法,可以有效避免因套接字读取操作导致的while循环阻塞问题。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

最全服务器模型详解——从单线程阻塞到多线程非阻塞

应用程序遍历套接字的事件检测 当多个客户端向服务器请求时,服务器端会保存一个套接字连接列表中,应用层线程对套接字列表轮询尝试读取或写入。...对于读取操作,如果成功读取到若干数据,则对读取到的数据进行处理;如果读取失败,则下一个循环再继续尝试。对于写入操作,先尝试将数据写入指定的某个套接字,写入失败则下一个循环再继续尝试。...这样看来,不管有多少个套接字连接,它们都可以被一个线程管理,一个线程负责遍历这些套接字列表,不断地尝试读取或写入数据。这很好地利用了阻塞的时间,处理能力得到提升。...内核遍历套接字的事件检测 这种方式将套接字的遍历工作交给了操作系统内核,把对套接字遍历的结果组织成一系列的事件列表并返回应用层处理。...这样就避免了遍历套接字的操作,但仍然有大量无用的数据(状态为0的元素)从内核复制到应用层中。于是就有了第二种事件检测方式。 内核基于回调的事件检测方式二如图所示。服务器端有多个客户端套接字连接。

2.8K50

庖丁解牛:NIO核心概念与机制详解 06 _ 连网和异步 IO

另一方面,异步 I/O 调用不会阻塞。相反,你将注册对特定 I/O 事件的兴趣 ― 可读的数据的到达、新的套接字连接,等等,而在发生这样的事件时,系统将会告诉你。...第二行将 ServerSocketChannel 设置为 非阻塞的 。我们必须对每一个要使用的套接字通道调用这个方法,否则异步 I/O 就不能工作。...删除处理过的 SelectionKey 在处理 SelectionKey 之后,我们几乎可以返回主循环了。但是我们必须首先将处理过的 SelectionKey 从选定的键集合中删除。...我们调用迭代器的 remove() 方法来删除处理过的 SelectionKey: it.remove(); 现在我们可以返回主循环并接受从一个套接字中传入的数据(或者一个传入的 I/O 事件)了。...在本例中,由于这是一个 echo server,我们只希望从套接字中读取数据并马上将它发送回去。

16830
  • 如何在Python中使用Linux epoll

    C10K问题讨论了用于处理多个并发套接字的一些替代方法,例如异步套接字的使用。 这些套接字在某些事件发生之前不会阻塞。 而是,程序在异步套接字上执行一个操作,并立即通知该操作成功还是失败。...第13行:由于默认情况下套接字是阻塞的,因此使用非阻塞(异步)模式是必需的。 第15行:创建一个epoll对象。 第16行:对服务器套接字上的读取事件感兴趣。...第23行:如果套接字服务器上发生读取事件,则可能已经创建了新的套接字连接。 第25行:将新套接字设置为非阻塞模式。 第26行:对新套接字的读取(EPOLLIN)事件感兴趣。...第39行:发送完完整的响应后,请停止对进一步的读取或写入事件感兴趣。 第40行:如果显式关闭了连接,则套接字关闭是可选的。此示例程序使用它来使客户端首先关闭。...在示例4中,第25、36和45行引入了循环,直到发生异常为止(否则,其他所有数据将被处理)。第32、38和48行捕获了预期的套接字异常。

    3.2K10

    并发服务器(三):事件驱动

    阻塞式 I/O 更好理解,因为这是我们使用 I/O 相关 API 时的“标准”方式。从套接字接收数据的时候,调用 函数会发生阻塞,直到它从端口上接收到了来自另一端套接字的数据。...这里就实现了使用非阻塞的 让监听者检查套接字变为可能,并且在没有数据的时候重新获得控制权。换句话说,用编程的语言说这就是轮询polling—— 主程序周期性的查询套接字以便读取数据。...首先,让我们谈谈主循环。它看起来是什么样的呢?先让我们想象一下服务器有一堆任务,它应该监视哪些东西呢?两种类型的套接字活动: 新客户端尝试连接。这些客户端应该被 。 已连接的客户端发送数据。...这个结构体告诉主循环,是否应该监视套接字的读取事件、写入事件,或者两者都监视。上述代码展示了 和 是怎么在合适的描述符集合中被调用的。...轮询需要一直发生,而 实际上会阻塞到有一个或多个套接字准备好读取/写入; 会比一直询问浪费少得多的 CPU 时间。

    1.6K50

    高性能网络通信框架Netty-Java NIO基础

    3.1 客户端程序 这个客户端功能是当客户端连接到服务端后,给服务器发送一个Hello,然后从套接字里面读取服务器端返回的内容并打印,具体代码如下: public class NioClient {...代码(6)(7)调用套接字通道的connect方法,连接服务器(服务器套接字地址为127.0.0.1:7001),由于步骤(3)设置了为非阻塞,所以步骤(6)马上会返回。...然后进入while循环进行事件处理,其中代码(8)选择已经就绪的网络IO事件,如果当前没有就绪的则阻塞当前线程。当有就绪事件后,会返回获取的事件个数,会执行代码(9)具体取出来具体事件列表。...代码(10.4)则看如果当前事件key是OP_READ事件,说明服务器发来的数据已经在接受buffer就绪了,客户端可以去具体拿出来了,然后代码10.4.1从客户端套接字里面读取数据并打印。...注:设置套接字为非阻塞后,connect方法会马上返回的,所以需要根据结果判断是否为链接建立OK了,如果没有成功,则需要设置对该套接字的op_connect事件感兴趣,在这个事件到来的时候还需要调用finishConnect

    60220

    linux网络编程之socket(九):使用select函数改进客户端服务器端程序

    出现上述问题的根本原因在于客户端程序不能并发处理从标准输入读取数据和从套接字读取数据两个事件,我们可以使用前面讲过的select函数来完善客户端程序,如下所示: void do_echocli(int ...循环中,如果select返回说明有事件发生,依次判断是哪些事件发生,如果是标准输入有数据可读,则读取后再次回到循环开头select阻塞等待事件发生,如果是套接口有数据可读,且返回为0则说明对方已经关闭连接...程序第一次进入while 循环,只把监听套接字加入关心的事件,select返回说明监听套接字有可读事件,即已完成连接队列不为空,这时调用accept不会阻塞,返回一个已连接套接字,将这个套接字加入allset...,因为第一次运行则nready = 1,直接continue跳回到while 循环开头,再次调用select,这次会关心监听套接字和一个已连接套接字的可读事件,如果继续有客户端连接上来则继续将其加入allset...服务完毕再次回到while 开头调用select 阻塞时,就关心一个监听套接字和2个已连接套接字的可读事件了,一直循环下去。

    3.8K00

    【Netty】NIO 选择器 ( Selector ) 通道 ( Channel ) 缓冲区 ( Buffer ) 网络通信案例

    NIO 通信 服务器端 流程说明 ---- NIO 网络通信 服务器端 操作流程 , 与 BIO 原理类似 , 基本流程是 启动服务器套接字通道 , 创建选择器 , 将服务器套接字通道注册给选择器 ,...监听客户端连接事件 , 客户端连接成功后 , 创建套接字通道 , 将新创建的通道注册给选择器 , 然后监听该通道的读取事件 ; 启动 -> 创建选择器 -> 创建服务器通道 -> 注册服务器通道 ->...: 并设置该通道网络通信模式为非阻塞模式 serverSocketChannel.configureBlocking(false) , 注意这里设置了非阻塞模式 , 其 对应的客户端套接字通道 SocketChannel...判定事件触发 : //阻塞监听, 查看是否有事件触发, 如果有就在下面处理 //如果没有 continue 终止循环, 继续下一次循环...创建套接字通道 : 调用 SocketChannel.open() 方法 , 即可获取套接字通道 ( SocketChannel ) , 之后将该通道设置为 非阻塞通信模式 socketChannel.configureBlocking

    70620

    深入剖析Linux网络设计中网络IO的重要角色

    EALREADY 套接字是非阻塞的,以前的连接尝试尚未完成。 EBADF 文件描述符不是描述符表中的有效索引。 EconRefuse 没有人监听远程地址。...例如,在尝试将UNIX域数据报套接字连接到流套接字时,可能会发生此错误。 ETIMEDOUT 尝试连接时超时。服务器可能太忙,无法接受新连接。...当流套接字对等端执行有序关闭时,返回值将为0;不同域(例如UNIX和Internet域)中的数据报套接字允许零长度数据报,当接收到这样的数据报时,返回值为0;如果从流套接字接收的请求字节数为0,则也可以返回值...recv的错误码: 错误码 含义 EAGAIN,EWOULDBLOCK 套接字标记为非阻塞,接收操作要求阻塞,或者设置了接收超时,并且在接收数据之前超时。...从缓冲区中读取数据。 //...... while(1) { //......

    11620

    Java NIO之套接字通道

    与文件通道不同,套接字通道可以运行在非阻塞模式下。...如果在连接未建立起来的情况下,从管道中读取,或向管道写入数据,会触发 NotYetConnectedException 异常。所以要进行循环检测,以保证连接完成建立。...非阻塞模式虽然不会阻塞线程,但是在方法返回后,还要进行循环检测,线程实际上还是被阻塞。...紧接着进入 while 循环,然后就可以和服务端愉快的聊天了。 上面的代码和叙述都没啥意思,最后我们还是来看看上面代码的运行效果,一图胜前言。...[u5j97apr0c.gif] 4.总结 到这里,关于套接字通道的相关内容就讲完了,不知道大家有没有看懂。本文仅从使用的角度分析了套接字通道的用法,至于套接字通道的实现,这并不是本文关注的重点。

    1.2K60

    从零开始手写Tomcat的教程4节---Tomcat默认连接器

    ,将 avaiable 设为 false 重新进入阻塞,得到用户的返回用户的 socket,最后就能够通过 process 处理请求了。...然后,有个 while 循环用来保持从输入流中读取,直到 HttpProcessor 被停止,一个异常被抛出或者连接给关闭为止。 while (!...否则,shutdownInput 方法将会调用,而套接字将被关闭. try { shutdownInput(input); socket.close(); shutdownInput 方法检查是否有未读取的字节...---- 解析连接 parseConnection 方法从套接字中获取到网络地址并把它赋予 HttpRequestImpl 对象。 它也检查是否使用代理并把套接字赋予请求对象。...循环,可以持续读取 HTTP 请求直到再也没有更多的头部可以读取到。

    85610

    【Netty】NIO 网络编程 聊天室案例

    ) , 注册给选择器 ; 服务器端的消息转发流程 : 服务器端收到客户端发送的消息 , 将该消息转发给除该客户端外的其它客户端 , 从选择器中可以获取到所有的 通道 , 注意 屏蔽 服务器套接字通道...服务器套接字通道 : 调用 open 静态方法创建服务器套接字通道 , 并绑定 8888 端口 , 设置非阻塞网络通信模式 ; // 创建并配置 服务器套接字通道 ServerSocketChannel...服务器端选择器 : 调用 open 静态方法获取 选择器 , 注册之前创建的 服务器套接字通道 ; // 获取选择器, 并注册 服务器套接字通道 ServerSocketChannel selector...处理客户端消息转发事件 : ① 读取客户端上传的数据 : 通过 SelectionKey 获取 通道 和 缓冲区 , 使用 套接字通道 ( SocketChannel ) 读取 缓冲区 ( ByteBuffer...连接服务器 : 连接服务器 , 并设置网络通信非阻塞模式 ; // 创建并配置 服务器套接字通道 ServerSocketChannel socketChannel = SocketChannel.open

    1.4K10

    网络编程基础第四讲阻塞模型

    这个就是我们常说的阻塞. 只要我们创建的套接字都是阻塞模型. 就是说数据接受不到不返回. 我们可以设置为非阻塞.就是不管数据有没有来到都会返回.如果来到.会有通知.我们可以编程接受数据....设置非阻塞模式方法   ioctlsocket(SOCKET s, long cmd, u_long *arpg); 改变套接字模式.为飞租she....阻塞迭代模式步骤   1.生成一个函数.绑定本地地址跟监听.   2.生成一个函数.专门接受一个客户端连接.并且返回对应连接的套接字.   3.处理没一个客户端的连接.实现接受跟发送数据.   4.关闭一个连接....绑定地址,开始监听 SOCKET BindAnListen(int nBacklog) { //创建套接字 BOOL bRet = FALSE; SOCKET hSocket...INVALID_SOCKET == hSocket) { DebugLog(TEXT("main Bind Fail")); goto Opt; } // 2.循环接受套接字连接

    35920

    Python升级之路( Lv16 ) 网络编程

    将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据....(flag)如果flag为0,则将套接字设为非阻塞模式,否则将套接字设为阻塞模式(默认值)....非阻塞模式下,如果调用recv()没有发现任何数据,或send()调用无法立即发送数据,那么将引起socket.error异常.s.makefile()创建一个与该套接字相关连的文件 2....关闭连接 s.close() 按顺序分别启动服务端模块(接收数据) 和 客户端模块(发送数据) 运行结果 持续通信 核心: 利用While循环让程序持续挂起, 并且设置一个点让循环关闭 实操:...关闭连接 tcp.close() 按顺序分别启动服务端模块(接收数据) 和 客户端模块(发送数据) 运行结果 持续通信 核心: 利用While循环让程序持续挂起, 并且设置一个点让循环关闭 实操:

    86220

    Python Socket通信黏包问题分

    [WinError 10013] 以一种访问权限不允许的方式做了一个访问套接字的尝试 原因:端口被占用导致 解决: Windows下 C:\> netstat -ano|findstr 8080...服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的连接,(阻塞式)等待连接的到来 客户端套接字函数...s.getsockname() 当前套接字的地址 s.getsockopt() 返回指定套接字的参数 s.setsockopt() 设置指定套接字的参数 s.close()...关闭套接字 面向锁的套接字方法 s.setblocking() 设置套接字的阻塞与非阻塞模式 s.settimeout() 设置阻塞套接字操作的超时时间 s.gettimeout...() 得到阻塞套接字操作的超时时间 面向文件的套接字的函数 s.fileno() 套接字的文件描述符 s.makefile() 创建一个与该套接字相关的文件

    55220

    一文读懂五大 IO 模型的前世今生( select、epoll、epoll)

    IO 是将第一阶段的等待读就绪改为非阻塞,但是第二阶段的数据读取还是阻塞的,非阻塞 read 最重要的是提供了我们在一个线程内管理多个文件描述符的能力。...这时我们自然而然就会想到把上述循环检测连接(文件描述符)可读的过程交给操作系统去做,从而避免频繁的进行系统调用。当然操作系统给我们提供了这样的函数:select、poll、epoll。...new Tread(){ while(select(arr) > 0){ for(connfd : arr){ if(connfd can read){ // 如果套接字可读...epoll 基于高效的红黑树结构,提供了三个核心操作,主要流程如下所示:伪代码:listenfd = socket(); // 打开一个网络通信套接字bind(listenfd); /...new Tread(){ while(arr = epoll_wait()){ for(connfd : arr){ // 仅返回可读套接字 newTheadDeal

    1.1K41

    Python与套接字

    () 被动接受TCP客户的连接,(阻塞式)等待连接的到来 客户端套接字函数 s.connect() s.connect_ex() s.connect_ex() connect()函数的扩展版本,出错时返回出错码...() 设置指定套接字的参数 s.close() 关闭套接字 面向锁的套接字方法 s.setblocking() 设置套接字的阻塞与非阻塞模式 s.settimeout() 设置阻塞套接字操作的超时时间...s.gettimeout() 得到阻塞套接字操作的超时时间 面向文件的套接字的函数 s.fileno() 套接字的文件描述符 s.makefile() 创建一个与该套接字相关的文件 第一版,单个客户端与服务端通信...read()/recv() 函数也是如此,也从输入缓冲区中读取数据,而不是直接从网络中读取。...,也可以readline,也可以for循环,但是读取出来的数据 大小就不固定了,影响效率,有可能读的比较小,也可能很大,像视频文件一般都是一行的二进制字节 流。

    2.4K30

    Unix的IO模型解析

    需要注意,实际读取的字节数可能小于数组的长度,方法的返回值正是实际读取的字节数。 非阻塞式IO 允许将一个套接字设置为非阻塞。...其模型如下 可以看到,在内核没有数据时,尝试对数据的读取不会导致线程阻塞,而是快速的返回一个错误。直到内核中收到数据时,尝试读取,就会将数据从内核复制到用户空间,进行操作。...IO复用 IO复用指的应用程序阻塞在系统提供的两个调用select或poll上。当应用程序关注的套接字存在可读情况(也就是内核收到数据了),select或poll的调用被返回。...一旦有了数据,内核等待结束,select调用也就返回了。 信号驱动IO ? 与非阻塞IO类似,其在数据等待阶段并不阻塞,但是原理不同。信号驱动IO是在套接字上注册了一个信号调用方法。...异步IO 异步IO的实现一般是通过系统调用,向内核注册了一个套接字的读取动作。这个调用一般包含了:缓存区指针,缓存区大小,偏移量、操作完成时的通知方式。

    50430

    C语言网络编程-tcp服务器实现

    非阻塞式TCP服务器 在c语言中,可以使用fcntl函数,将套接字设置为非阻塞的 #include  #include //inet_addr() sockaddr_in...,无法读取返回-1                 continue;             }             if (str_length == 0)    //读取数据完毕关闭套接字             ...,如果全部socket无法读取(没有事件变化),则相当于是while(1),会使cpu繁忙     } } 这样,我们就实现了一个单进程多客户端的tcp服务器了,不需要多进程也能实现多客户端,但是看最后一行注释能发现一个问题...:非阻塞下,会无限循环,让代码空转,这样浪费的性能也是巨大的,那我们该怎么完善呢?...accept直到没有数据可读, 由于必须一直循环读取,所以当accept没有数据可读时,必须是非阻塞模式,否则会阻塞 实现代码 #include  #include <arpa/inet.h

    6.1K62
    领券