套接字api-UDP套接字编程

recvfrom,sendto

ssize_t recvfrom(
	int sockfd,
	void* buff,
	size_t nbytes,
	int flags,
	struct sockaddr* from,
	socklen_t *addrlen);
ssize_t sendto(
	int sockfd,
	const void* buff,
	size_t nbytes,
	int flags,
	const struct sockaddr* to,
	socklen_t addrlen);

使用sendto/recvfrom发送和接收数据量为0的数据报是允许的.
recvfrom返回0,并不意味着收到对端FINsendto,recvfrom使用的场景下没有连接的概念)

注意点

每个UDP套接字有一个接收缓冲区.到达该套接字的每个数据报都进入这个套接字的接收缓冲区.
当进程针对此UDP套接字调recvfrom时,从缓冲区取出一个数据报返回给进程.UDP一般无发送缓冲区.

sendto

sendto时,若关联的套接字未绑定一个明确的本地端口,本地IP.发出数据报的源IP,源端口会由内核自动指定.sendto在将数据报送到本机某接口输出队列即返回.

若后续此数据报发送时遭遇失败,对未执行bind+connectUDP套接字,应用无法获知之前发送失败的信息.
对执行了bind+connectUDP套接字,可获知之前发送失败的信息.
未执行bind+connectUDP套接字,首次sendto时,内核确定该套接字本端端口,且后续维持不变.每次sendto时,内核依据数据报实际外出接口,确定其本端IP
服务端要向确认本次接收数据报的目的IP,对IPV4,设置IP_RECVDSTADDR+recvmsg,对IPV6,设置IPV6_PKTINFO+recvmsg是一种可取的方法.服务端要确认本次接收数据报的目的端口,用getsockname即可.

recvfrom,若关联的套接字未绑定一个明确的本地IP
在弱端系统下,只要数据报目的地址为本机IP地址之一,即使数据报到达接口和其目的地址不一致,也能被本机接收.
这种情况下,有时,我们希望知道所接收数据报的目的IP是什么
一种方法:
多宿主机上,针对每个本机IP+服务端口创建一个套接字,且对所有此服务的套接字调selectselect返回时,对应套接字的本机IP即为其所收到数据报的目的IP

这样产生一种情形:
客户A通过UDP套接字S1向一个指定IP地址,端口号的主机发UDP消息M1.然后客户等待接收回复.
指定IP地址的主机上,一个未绑定IP地址的UDP套接字D1在指定端口上等待接收请求.
D1会收到M1,然后发回回复A M1
A M1的源IP地址会由内核设定为外出接口的IP地址.(可能和客户指定的IP地址不同,因为此主机有多个IP地址)

客户A收到回复A M1A M1的源IP地址和客户A发送请求时使用的目的IP地址不同.但此回复确实是来自目的主机的回复.
要解决此问题,可选的方案是:
客户把发送请求的目的IP地址借助DNS得到主机名.客户把收到回复的源IP地址也用DNS得到主机名.两种如果匹配,则即为目的主机发回的回复.

sendto在把数据报放入主机某接口外出输出队列后,即成功返回.但后续传输数据有可能发生错误.但错误无法通知到应用.仅仅在UDP套接字采用connect关联到一个确定的对端时,诸如发生对端不可达,对端相应端口没套接字等才会通知到应用.

connect

UDPconnect
1.没有三路握手
内核检查是否存在已知错误,记录对端IP地址,端口号,立即返回.

2.connectUDP套接字
a. 未连接UDP套接字
b. 已连接UDP套接字
后续用此套接字send时,不必指定目的IP,目的端口.(改用send/write替代sendto
后续用此套接字recv时,不必获取源IP,源端口.(改用read/recv/recvmsg替代recvfrom
只有目的IP+目的端口为此套接字本端IP和本端端口,源IP+源端口为connect指定的IP和端口的数据报,才会投递到本UDP套接字.
UDP执行connect时,若之前未对其执行bind,则内核此时设置其本端IP+本端端口,且设置后维持不变.(因为维持不变,所以可用getsockname获取这些信息)后续用此套接字send时,产生了异步错误,进程可在recv时获知.

2.对UDP套接字多次调connect
TCP套接字只能调connect一次,对已经连接UDP套接字再次调connect.若把套接字地址结构的地址族设为AF_UNSPEC,地址结构其余部分全部为0,可用于断开连接.若connect指定了正常的主机IP+端口,相当于对连接定向到另一个目的地.

UDP中的外出接口

connect执行后,返回的套接字不仅绑定了目的IP,目的端口.还绑定了本地IP,本地端口.

高级UDP

1.确定外来UDP数据报目的地址
若实现支持IP_RECVDSTADDR选项,用选项
若不支持,捆绑所有接口地址+select
2.UDP优势
a. 如要使用广播,多播,则必须用UDP
b. UDP没有连接建立,拆除开销

3.TCP优势
a. 接收确认机制(用于保证有序接收,识别重传)
b. 流量控制
接收端可以告知发送端自己的接收缓冲区大小,发送端未确认数据量不能超过告知的缓冲区大小
c. 慢启动,拥塞避免

原则:
a. 多播,广播必须用UDP
b. 非持续,短连接适合UDP,如需可靠性,需在应用层添加序号,超时,重传,流量控制,拥塞避免等特性.
c. 持续的长连接适合TCP

UDP下服务端想采用并发模型,常见模式为:
服务端在服务端口绑定套接字,等待读取客户申请,读到申请后,fork子进程,子进程中创建新UDP套接字A,绑定临时端口,发给客户回复.此后客户向子进程的套接字A发送请求与接收回复.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

raindayinrain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值