UDP服务recvfrom函数设置非阻塞



基本概念:

其实UDP的非阻塞也可以理解成和TCP是一样的,都是通过socket的属性去做。

方法一:通过fcntl函数将套接字设置为非阻塞模式

方法二:通过套接字选项SO_RECVTIMEO设置超时。


方法一源码,编译:g++ udp_server.cpp -o server

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>

void Perror(const char *s)
{
    perror(s);
    exit(EXIT_FAILURE);
}

//设置非阻塞
static void setnonblocking(int sockfd) {
    int flag = fcntl(sockfd, F_GETFL, 0);
    if (flag < 0) {
        Perror("fcntl F_GETFL fail");
        return;
    }
    if (fcntl(sockfd, F_SETFL, flag | O_NONBLO
<think>好的,我现在要回答用户关于recvfrom函数是否会阻塞的问题。首先,我需要回忆一下recvfrom函数的基本用法和相关知识。recvfrom是用于套接字编程的一个函数,主要用于接收数据报,并获取发送方的地址信息。 用户的问题是关于阻塞的,所以我要考虑recvfrom在不同情况下的行为。首先,阻塞和非阻塞模式的区别。默认情况下,套接字是阻塞模式的,这意味着当调用recvfrom时,如果没有数据可用,进程会被挂起,直到有数据到达或者发生错误。这种情况下,recvfrom确实会阻塞。 但是,如果套接字被设置非阻塞模式,那么当没有数据可读时,recvfrom会立即返回一个错误,通常是EWOULDBLOCK或EAGAIN。这时候函数就不会阻塞,而是让程序继续执行其他任务。所以,是否阻塞取决于套接字的模式设置。 接下来,我需要考虑不同的套接字类型,比如TCP和UDP。虽然recvfrom通常用于无连接的协议如UDP,但它也可以用于TCP,不过TCP通常是面向流的,一般使用recv或read。但无论协议如何,阻塞行为主要还是由套接字的模式决定。 另外,超时设置也可能影响阻塞行为。有些情况下,即使套接字是阻塞的,可以通过设置超时选项(如SO_RCVTIMEO)来让recvfrom在指定时间后返回,避免无限期阻塞。这时候,函数会在超时后返回错误,而不是一直阻塞。 还需要考虑错误处理的情况。比如,如果套接字被关闭,或者发生其他错误,recvfrom会返回相应的错误码,这时候可能不会阻塞,而是直接返回。 总结起来,用户需要知道recvfrom是否会阻塞主要看两点:套接字的阻塞/非阻塞模式,以及是否设置了超时选项。默认情况下是阻塞的,但可以通过设置改变这一行为。同时,不同的协议使用recvfrom的情况可能不同,但阻塞行为的关键因素还是套接字模式。 在组织回答时,应该分点说明,结构清晰。首先明确回答会还是不会,然后解释在不同情况下的行为,包括默认情况、非阻塞模式、超时设置等。最后给出示例代码片段,帮助用户理解如何设置非阻塞模式或超时。同时提醒用户根据具体需求选择合适的模式,并注意错误处理。</think>recvfrom函数是否阻塞取决于套接字的配置模式,具体分析如下: ### 1. **默认行为(阻塞模式)** - **会阻塞**:当套接字处于`阻塞模式`(默认状态)时: - 若接收缓冲区中**无数据**,`recvfrom`会一直等待,直到: - 数据到达 - 连接被关闭(如TCP) - 信号中断(如用户按Ctrl+C) - 示例代码: ```c ssize_t recv_len = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr*)&src_addr, &addr_len); // 执行到此行时,若无数据则阻塞 ``` ### 2. **非阻塞模式** - **不会阻塞**:若套接字通过`fcntl`或`ioctl`设置为`非阻塞模式`: - 当无数据可读时,`recvfrom`立即返回错误码`EWOULDBLOCK`/`EAGAIN` - 需手动检查返回值: ```c // 设置非阻塞 int flags = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); ssize_t recv_len = recvfrom(...); if (recv_len == -1 && errno == EWOULDBLOCK) { // 无数据,继续执行其他任务 } ``` ### 3. **超时控制** - **有限阻塞**:通过设置`SO_RCVTIMEO`选项可指定超时时间: ```c struct timeval tv; tv.tv_sec = 2; // 最多阻塞2秒 tv.tv_usec = 0; setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); ssize_t recv_len = recvfrom(...); if (recv_len == -1 && errno == EWOULDBLOCK) { // 超时后返回 } ``` ### 4. **协议差异** - **UDP**:无连接协议,`recvfrom`直接等待新数据报。 - **TCP**:面向连接协议,通常用`recv`,但`recvfrom`也可用。若连接关闭,返回0。 ### 总结建议 | 场景 | 行为 | 适用场景 | |------------------|--------------------|----------------------------| | 默认阻塞模式 | 无限等待数据 | 简单同步通信 | | 非阻塞模式 | 立即返回 | 需同时处理多任务的异步程序 | | 设置超时 | 有限等待 | 需响应时间保障的系统 | 实际开发中应结合需求选择模式非阻塞模式通常需配合`select`/`poll`/`epoll`等I/O多路复用技术。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值