Socket 非阻塞模式下connect 返回EINPROGRESS(115)错误

本文探讨了在非阻塞socket环境下,客户端首次connect操作返回errno 115的问题。通过将socket设置为阻塞模式,或利用select/poll判断socket可写状态,解决了连接异常中断的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天再测试socket的时候,发现一个很奇怪的问题,就是客户端再connect的时候第一次connect总是会返回-1,errno是115,往往第二次连接就可以成功了。但是对于服务端来说,第一次连接已经成功返回了。后来想想可能跟自己的设置socket是非阻塞的有关系,后来吧socket设置成阻塞的,问题确实就没有了。

后来有反复尝试了非阻塞的。我先把服务器关闭,让客户端连接,可以发现从打出来的errno中发现115和111一组,循环出现。

 

两种方案

1)先设置socket为阻塞,待connect连接成功后改成非阻塞

2)connect返回115时,需要判断socket是否可写,如果时可写的话则连接成功

通过select 或者poll判断可写https://blog.youkuaiyun.com/saspss/article/details/8487678

3)个人实验,第一次connect返回EINPROGRESS可再次connect,如果没问题就证明成功 

<think>嗯,用户问的是socket非阻塞模式,我得先理清楚这个概念。首先,socket是网络编程的基础,非阻塞模式应该和I/O模型有关。那阻塞和非阻塞的区别是什么来着?阻塞模式下,当程序执行一个网络操作,比如recv(),如果没有数据可读,线程就会一直卡在那里,直到有数据到达。而非阻塞模式的话,调用会立即返回,不管有没有数据,这样程序可以继续做其他事情,不需要等待。 接下来需要解释非阻塞模式的特点。比如,当设置为非阻塞后,调用accept、connect、recv、send这些函数时,如果没有立即完成,会返回一个错误码,比如EAGAIN或者EWOULDBLOCK。这时候程序应该处理这个错误,而不是一直阻塞。这能提高程序的响应能力,特别是在需要同时处理多个连接的时候。 然后,用户可能想知道如何设置socket非阻塞模式。不同的系统有不同的方法,比如在Linux下可以用fcntl设置O_NONBLOCK标志,而Windows下则是ioctlsocket函数。这部分需要具体说明,最好给出代码示例,比如用fcntl的步骤:获取当前标志,加上非阻塞标志,再设置回去。 还要讨论非阻塞模式的应用场景。比如高并发服务器,比如游戏服务器或者实时通信系统,这些需要同时处理大量连接的地方,用非阻塞模式结合I/O多路复用(如select、epoll)会更高效。不过也要提到缺点,比如编程复杂度增加,需要循环检查状态,处理错误,可能消耗更多CPU资源。 用户可能还关心与非阻塞模式相关的其他技术,比如异步I/O、多路复用机制(select、poll、epoll)。需要比较这些技术的异同,说明非阻塞模式通常是这些机制的基础。 然后要总结非阻塞模式的优缺点。优点包括提高并发性、资源利用率,避免线程阻塞;缺点是代码复杂,调试困难,可能忙等消耗CPU。 最后,给出一个简单的代码示例,展示如何设置socket非阻塞,并进行错误处理。比如用fcntl设置,然后尝试accept,如果返回EAGAIN就等待或者处理其他任务。 需要确保回答结构清晰,分点说明,使用中文,同时注意数学公式的正确LaTeX格式,但这个问题可能不涉及数学公式,所以可能不需要用。不过如果有提到什么算法或公式,要用对应的格式。但socket非阻塞模式更多是概念和代码,所以重点在代码示例和步骤说明。 检查是否遗漏了重要点,比如非阻塞模式下的connect如何处理,可能返回EINPROGRESS,需要用select等检查连接是否完成。这也是一个关键点,需要补充到流程中。 另外,要注意用户可能混淆非阻塞和异步的概念,需要区分两者。异步I/O可能在操作完成后通过回调通知,而非阻塞则需要主动轮询,所以两者的机制不同。 最后确保语言通俗,避免过于技术化的术语,但也要准确。可能需要分步骤解释,比如如何设置,如何处理返回错误,如何结合多路复用等。</think>Socket 非阻塞模式是网络编程中一种重要的 I/O 模型,其核心目标是避免线程因等待 I/O 操作而阻塞。以下是逐步解析: --- ### **1. 阻塞与非阻塞的本质区别** - **阻塞模式**:当调用 `recv()`, `accept()`, `connect()` 等函数时,若操作无法立即完成(如无数据可读、无新连接到达),线程会**暂停执行**,直到条件满足。 - **非阻塞模式**:无论操作是否完成,函数都会**立即返回**。若操作未完成,会返回错误码(如 `EWOULDBLOCK` 或 `EAGAIN`),线程可继续执行其他任务。 --- ### **2. 如何设置非阻塞模式** #### **Linux/Unix 系统** ```c #include <fcntl.h> int flags = fcntl(sockfd, F_GETFL, 0); // 获取当前标志 fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); // 添加非阻塞标志 ``` #### **Windows 系统** ```c #include <winsock2.h> u_long mode = 1; // 1 表示非阻塞,0 表示阻塞 ioctlsocket(sockfd, FIONBIO, &mode); ``` --- ### **3. 非阻塞操作的行为** - **读操作**(`recv`):若无数据可读,立即返回错误码。 - **写操作**(`send`):若内核缓冲区已满,立即返回错误码。 - **连接操作**(`connect`):若无法立即完成,返回 `EINPROGRESS`,需后续通过 `select` 或 `getsockopt` 检查连接状态。 --- ### **4. 错误码处理示例** ```c ssize_t n = recv(sockfd, buffer, sizeof(buffer), 0); if (n == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) { // 无数据可读,稍后重试 } else { // 真实错误(如连接断开) } } ``` --- ### **5. 与非阻塞模式配合的技术** - **I/O 多路复用**:通过 `select`、`poll`、`epoll`(Linux)或 `kqueue`(BSD)**监控多个 socket 状态**,避免忙等。 - **事件循环**:在单线程中高效处理多个连接的读写事件,典型应用于 Nginx、Redis 等高性能服务。 --- ### **6. 典型应用场景** 1. **高并发服务器**:单线程同时处理成千上万个连接。 2. **实时系统**:如游戏服务器需快速响应多个客户端。 3. **异步任务**:避免 I/O 操作阻塞主逻辑线程。 --- ### **7. 优缺点对比** | **优点** | **缺点** | |-----------------------------------|-----------------------------------| | 提高 CPU 利用率 | 需处理复杂的状态检查和错误码 | | 避免线程上下文切换开销 | 代码复杂度显著增加 | | 单线程即可实现高并发 | 需配合多路复用机制避免忙等 | --- ### **8. 与非阻塞相关的关键问题** - **数据边界处理**:非阻塞模式下,`send` 和 `recv` 可能无法一次性完成,需实现**缓冲区管理**。 - **连接超时控制**:非阻塞 `connect` 需手动设置超时检测逻辑。 - **公平调度**:需避免某个 socket 长期占用 CPU(如通过轮询权重机制)。 --- ### **9. 代码片段:非阻塞 accept 示例** ```c int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 设置非阻塞 fcntl(sockfd, F_SETFL, O_NONBLOCK); while (1) { int client_fd = accept(sockfd, NULL, NULL); if (client_fd == -1) { if (errno == EAGAIN) { // 无新连接,处理其他任务 usleep(1000); // 避免忙等 } else { perror("accept error"); break; } } else { // 处理新连接 } } ``` --- ### **总结** 非阻塞模式通过**立即返回 + 错误码反馈**的机制,使程序能够高效管理多个 I/O 操作,但其代价是代码复杂度的显著上升。实际开发中通常结合**多路复用**和**事件驱动架构**,在资源利用率和开发效率间取得平衡。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值