【奇】udp的recvfrom

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【奇】udp的recvfrom相关的知识,希望对你有一定的参考价值。

A创建一个udp套接字, 绑定到(IP1, PORT1), 开两个线程, 一个发送, 一个接收
B也是创建一个udp套接字, 绑定到(IP2, PORT2), 开两个线程, 一个发送, 一个接收
A和B相互可以发送和收到数据
然后B关闭套接字退出, 重新创建一个udp套接字, 绑定到(IP2, PORT3), 开两个线程, 一个发送, 一个接收
【注意】调试的时候, 发现在A调用recvfrom()后, 参数from的地址自动变成(IP2, PORT3), 并能接收到C发来的数据, C也可以接收到A
怎么会出现这样的情况, recvfrom()函数为什么会改变from参数的值?
===========================================================
后来在同一台机子上调试也是一样, 只要B退出重新绑定到新的端口, A在调用recvfrom()后, from的端口会自动变成B的【新端口】, A和B双方又可以通信了, 非常奇怪, 不是吗?
====================
A和B的套接字都把SIO_UDP_CONNRESET选项设置为false, 不知道是这个的原因不????

UDP本来就是这样的,不需要绑定IP,只需要绑定一个端口,Sendto函数会附带IP信息,recv的时候会解析进来连接的地址。因为udp没有固定的连接,所以不知道进来的连接的IP,只能通过recv函数去实时获取,这是UDP最基本的机制。追问

'不需要绑定IP'是什么意思, 直接绑定0.0.0.0旧可以吗, sendto()会自动找到一个合适的本地ip?

recvfrom会自动解析对方地址, 哪还要from参数干什么, 这样recvfrom()的套接字不成了类似TCP的监听套接字吗?接收不乱套了吗?而且微软关于recvfrom()的官方文档上没有这样的说明啊!

大哥能不能提相关资料

追答

绑定地址的时候,如果只绑定端口,表示接受该端口下任何IP发来的数据,如果绑定IP和端口表示接受该IP和端口的数据,然后recvfrom函数在流中有数据可读的时候,会把该数据源的IP和端口解析出来,然后再根据该IP做相应的处理就可以了。UDP对端地址信息,都是从recvfrom函数中读取出来的。

追问

1, 还是不明白, 只绑定端口的话, bind()参数中的sockaddr_in.sin_addr该怎么填写

2, recvfrom()的参数form表明要接收指定ip和port的数据, 为什么还会收到其他端口的消息

3, 照你这样说的好像udp不遵守五元组原则啊, 本例中的五元组是(udp, ip1, port1, ip2, port2)
A的五元组没变, 却收到了(ip2, port3)的消息

追答

额...先了解一下UDP通信的一些基本概念吧,网上应该有很多啊,如果只绑定端口的话,sin.addr可以不用管啊。

recvfrom()接收绑定地址上发来的数据,也就是bind了什么地址,就接受什么地址的数据,如果只绑定一个端口,就接受这个端口所有IP发过来的数据。
这个函数的那个地址参数,是这个数据报的源地址,也就是谁发过来的。也就是说这个函数的地址参数是输出的,不是输入的。

比如说你只绑定了一个端口,然后收到了一条数据,这个数据来源的IP是什么呢,那就是recvfrom这个函数中解析出来的地址了。

参考技术A 你的from是哪个值?追问

追答

我的意思是你的from值从哪里读取的?

追问

两个线程共用一个套接字和from, 都是全局变量, 一个senddo()发送, 一个recvfrom()接收, 而且不会是sendto()改变from的, 已经单步调试过了
from是已知的, 因为实验中A和B都是用已知的ip和端口绑定, 而且在from的所有实例上下了断点, 只有recvfrom()函数会改变from的值.

UDP的sendto和recvfrom,数据是怎么按照协议处理的?

我对利用SOCKET收发UDP数据的理解是:sendto的时候,所发送的数据加上UDP报头封装成帧,然后发送;recvfrom的时候,所接收的数据是帧去掉UDP报头的内容--比如
WSABUF wsabuf;
wsabuf.buf=new char[1024];
wsabuf.len=1024;
DWORD dwRead;
DWORD dwFlag=0;
WSARecvFrom(m_socket, &wsabuf, 1, &dwRead, &dwFlag, (SOCKADDR*) &addrFrom, &len, NULL,NULL)
这里,wsabuf.buf的数据是去掉UDP报头的,而wsabuf.len也是不包含UDP报头的(如果缓冲区不满,wsabuf.len就是缓冲区里的有的数据的长度)...
大神求助,我的理解可否正确?对UDP和SOCKET理解不够深刻,望大神指导,不胜感激!

参考技术A 自己接收到完整的包,再处理这个包追问

这句话太抽象了,小弟理解不了啊!
接收到完整的包,怎样叫做完整的包,这完整的包都包含哪些内容?
比如发送2048字节16进制的字符,要接收这些字符,怎样才是完整的包,接收到的就是这些16进制字符吗?还包含其他内容(UDP报头什么的)吗?
处理这个包,又要怎么理解?
大神啊,帮助一下啊!

以上是关于【奇】udp的recvfrom的主要内容,如果未能解决你的问题,请参考以下文章

Golang开发面经奇安信(两轮技术面)

2018年爱奇艺校招笔试

Linux客户端和Window服务器端udp socket通信不能成功

百度2020秋招提前批一面面经(测试开发岗)

什么是奇函数和偶函数?

Zabbix怎么监控奇安信网神防火墙