使用recvfrom()接收UDP包在Windows和Linux平台的不同表现

1 UDP接收原理

操作系统的UDP接收流程如下:收到一个UDP包后,验证没有错误后,放入一个包队列中,队列中的每一个元素就是一个完整的UDP包。当应用程序通过recvfrom()读取时,OS把相应的一个完整UDP包取出,然后拷贝到用户提供的内存中,物理用户提供的内存大小是多少,OS都会完整取出一个UDP包。如果用户提供的内存小于这个UDP包的大小,那么在填充慢内存后,UDP包剩余的部分就会被丢弃,以后再也无法取回。

这与TCP接收完全不同,TCP没有完整包的概念,也没有边界,OS只会取出用户要求的大小,剩余的仍然保留在OS中,下次还可以继续取出。

socket编程虽然是事实上的标准,而且不同平台提供的接口函数也非常类似,但毕竟它不存在严格的标准。所以各个平台的实现也不完全兼容。下面就从recvfrom()这个函数看看Window平台和Linux平台的不同。

2 Windows平台的表现

先看头文件中的声明:

int
WSAAPI
recvfrom(
    _In_ SOCKET s,
    _Out_writes_bytes_to_(len, return) __out_data_source(NETWORK) char FAR * buf,
    _In_ int len,
    _In_ int flags,
    _Out_writes_bytes_to_opt_(*fromlen, *fromlen) struct sockaddr FAR * from,
    _Inout_opt_ int FAR * fromlen
    );

再看MSDN说明:

If the datagram or message is larger than the buffer specified, the buffer is filled with the first part of the datagram, and recvfrom generates the error WSAEMSGSIZE. For unreliable protocols (for example, UDP) the excess data is lost.

可以看出,buf大小小于UDP包大小的时候,recvfrom()会返回-1,并设置错误WSAEMSGSIZE。

实际编程测试验证确实是这样的表现。

3 Linux平台的表现

先看头文件中的声明:

__extern_always_inline ssize_t
  recvfrom (int __fd, void *__restrict __buf, size_t __n, int __flags,
        __SOCKADDR_ARG __addr, socklen_t *__restrict __addr_len)

可以看出与Windows平台的函数原型相同。但是在其man手册里,没有看到UDP包大于接收缓冲区情况的特殊说明。

写代码测试表明,buf小于UDP包大小的时候,recvfrom()仍然返回复制到缓冲区的字节数,调用者无法得知UDP包被截断的情况。

4 写代码注意事项

UDP包不会大于底层的MTU,否则无法发送,在以太网上也就无法大于1500。虽然对于Windows平台,recvfrom()能够提示调用者buf过小的问题,但是即使得到了这个错误,包还是被丢弃了。所以在接收UDP包是,提供的buf要足够大,建议设为1500就行了,这样就避免了包被截断的情况。

时间: 2024-08-29 17:29:27

使用recvfrom()接收UDP包在Windows和Linux平台的不同表现的相关文章

ArcGIS Python 安装其它扩展包(Windows与Linux)

ArcGIS Python 安装其它扩展包(Windows与Linux) 下载 ? https://pypi.org/project/setuptools/#files ? setuptools-40.6.2.zip ? https://pypi.org/project/pip/#files ? pip-18.1.tar.gz ? 解压 ? ? 安装 setuptools ArcGIS Desktop(Windows) ? cd D:\software\setuptools-40.6.2 ? C

网络包排错指南-类linux 平台

网络包排错指南-类linux 平台 背景信息 最近一直在测试k8s,如果你了解或者解接触过docker,那你一定知道docker 相关的网络很大部分在桥接.路由.Iptables 上做文章.如果你凑巧接触过k8s,并且了解其后面的原理,那你一定知道kube-proxy 把iptables 玩的简直要飞起来.当然你可能会想到一些排错工具,比如我之前常用的抓包工具,或者路由跟踪工具,但这些工具在目前这样复杂的环境下,是不太趁手的,特别是包在本机的多个网卡或者虚拟网卡里转来转去,还有很多个iptabl

spring cloud 打成jar包在Windows或者Linux上运行的

整理一下关于Spring Boot后台运行的一些配置方式.在介绍后台运行配置之前,我们先回顾一下Spring Boot应用的几种运行方式 1:运行Spring Boot的应用主类2:使用Maven的Spring Boot插件mvn spring-boot:run来运行3:打成jar包后,使用java -jar运行 我们在开发的时候,通常会使用前两种,而在部署的时候往往会使用第三种.但是,我们在使用java -jar来运行的时候,并非后台运行.下面我们分别针对Windows和Linux/Unix两

Windows 和 Linux 平台下的端口转发工具

原文地址: http://unmi.cc/windows-linux-port-forwarding/ 这里记录一下我曾经使用过的几个端口转发工具,即端口映射.端口重定向,和 NAT 也是差不多的概念. Linux 下用过 iptables,rinetd:Windows 下用过某个防火墙的 NAT 功能.RemoteAnywhere 的端口重定向.FPipe,还有最近刚找到的 PassPort.试着去设置一下 Windows 2000 的 NAT  功能,但未成功,还是特定的软件简单易用,下面介

tomcat https/ssl 服务配置(带有双向验证,windows,linux平台验证通过)

1. 创建服务器密钥,其密钥库为 /home/gr/server.ks PS1: 注意keypass和storepass保持一致,它们分别代表 密钥密码和密钥库密码, PS2: 注意 CN=localhost 中,localhost表示要配置SSL的主机名,不能任意指定 ~$keytool -genkey -v -alias serverKey -dname "CN=192.168.10.101" -keyalg RSA -keypass 123456 -keystore server

Mongodb在windows和linux平台的安装配置

配置和环境: win10(本机)和linux(CentOs7)内网服务器各一台. Mongodb版本:3.07 一.windows 安装Mongodb 1.首先从官网下载mongo.我是win7 64bit 所以下载此版本. 链接:https://www.mongodb.org/downloads#production 2.创建数据目录 Mongodb将数据目录存储在db目录下.但这个目录不会主动创建,需要自己创建.我在D:\data\下建立db:也就是D:\data\db 3.试试能否正常运行

hadoop-2.2.0配置eclipse插件(windows和linux平台)

目前配置eclipse插件主要有两个版本,一个是在windows下重新编译配置,另一个是在linux在重新配置编译. 下面逐步讲解在linux下编译-配置eclipse插件的过程. 环境: Ubuntu 12.04 64bit 3.2.0-29-generic eclipse-jee-luna-R-linux-gtk-x86_64.tar.gz Apache Ant(TM) version 1.8.2 JDK Version 1.7.0_67 安装前准备: Ant.jdk.eclipse.Apa

windows和linux平台下的通用时间测试函数

Time.cpp ////////////////////////////////////////////////////////////////////////////// // Timer.cpp // ========= // High Resolution Timer. // This timer is able to measure the elapsed time with 1 micro-second accuracy // in both Windows, Linux and U

发送和接收数据包

发送和接收数据包 原文:Game Networking系列,作者是Glenn Fiedler,专注于游戏网络编程相关工作多年. 概述 在之前的网游中的网络编程系列1:UDP vs. TCP中(推荐先看前面那篇),我们经过讨论得出:网游中传输数据应该使用UDP而不是TCP.我们选择UDP是为了不需要等待重发数据包,从而达到数据的实时性. 注意,因为接下来英文原文中所有的代码是C++写的,而我是个pythoner,我的计划是:通过理解文章,我用python实现UDP收发数据包.虚拟连接(原文后两章的