网络编程-基于UDP的Socket网络编程(补充)

序言

本文补充介绍UDP Socket高级编程和一些UDP Socket零散知识。


1. 零散知识点补充


[1]. 乱序问题

  • 现象

    • 乱序就是发送数据的顺序和接收数据的顺序不一致,例如发送数据的顺序为A、B、C,但是接收到的数据顺序却为:A、C、B。
  • 原因

    • UDP不保证可靠接收。
    • 每个数据报走的路由并不一样,有的路由顺畅,有的却拥塞,导致每个数据报到达目的地的顺序不一样。
  • 解决方法

    • 使用RTP协议加入顺序控制机制(sequence number,序列号)


[2]. UDP缓冲区

  • 现象

    • 使用默认UDP接收缓存,发生UDP丢包
  • 原因

    • 数据包发送过快或数据包过大导致
  • 解决方法

    • 见我的另一篇博客:http://blog.csdn.net/baidu_35692628/article/details/76165337
  • 关于UDP缓冲区的两点说明

    • UDP缓冲区有接收缓冲区发送缓冲区,大小有默认值最小值最大值

    • 内核使用的UDP缓冲区是环形缓冲区,通过修改默认值和setsocketopt修改,增大了接收队列


[3]. UDP接收机制

  • socket一次能够send的UDP数据长度

    • UDP报头长度字段2字节,16比特,最长65535B即64K,考虑到UDP报头长度8字节,IP报头20字节,socket一次发送的长度不能超多65535 - 28 = 65507,否则返回错误
  • UDP接收机制

    • recvfrom接收一次一个包,接收失败返回-1,接收成功返回数据包长度

      • 不会只返回包的一部分,包不完整会丢弃整个数据包
    • 比如发端发送两个长度分别为300B,200B字节,则recvfrom接收返回值为300,200或200,300


[4]. 阻塞和非阻塞接收

UDP接收函数:recvfrom

TCP接收函数:recv

  • 阻塞接收

    • 数据到来进行接收

      • TCP:缓冲区至少有一个字节
      • UDP:缓冲区至少有一个完整的数据报
    • 没有数据处于睡眠状态

  • 非阻塞接收

    • 数据到来进行接收

      • TCP:缓冲区有任何一个字节则返回数据大小
      • UDP:缓冲区有一个完整的数据报,返回接收到的数据大小
    • 没有数据返回错误码


2. UDP Socket高级编程


[1]. UDP套接字

  • UDP套接字分类

    我们知道,TCP客户端有connnect()函数,在UDP中其实也有connect函数,UDP网络编程中的connect函数仅用于表示确定了另一方的地址,并没有其他含义。据此可以将UDP套接字分为

    • 未连接的UDP套接字(未使用connect函数进行地址确认的UDP连接),也就是我们常用的UDP套接字

      • 使用sendto/recvfrom进行信息的收发,目标主机的IP和端口是在调用sendto/recvfrom时确定
    • 已连接的UDP套接字

      • 对于已连接的UDP套接字,必须先经过connect来向目标服务器进行指定,然后调用read/write进行信息的收发,目标主机的IP和端口是在connect时确定的,也就是说,一旦conenct成功,我们就只能对该主机进行收发信息了
  • 发包效率

    • 未连接的UDP套接字,两个数据报调用sendto函数,内核将执行以下六个步骤

      • 连接套接字
      • 输出第一个数据报
      • 断开套接字连接
      • 连接套接字
      • 输出第二个数据报
      • 断开套接字连接
    • 已连接的UDP套接字,两个数据报调用write函数,内核将执行以下三个步骤

      • 连接套接字
      • 输出第一个数据报
      • 输出第二个数据报

      由此可见,当应用进程给同一个目的地址发送多个数据报时,连接套接字效率更高


[2]. 基于connect的套接字通信框架

  • 客户端/服务器通信框架

网络编程-基于UDP的Socket网络编程(补充)_第1张图片

  • 基于connect的套接字通信,与常用的UDP套接字通信相比,只是多了一个connect的过程。如下
void UdpHandler(int socketfd, struct sockaddr* dest)
{
    char buf[1024] = "UDP Socket Test!";
    int len = 0;

    connect(socketfd, dest, sizeof(*dest);

    len = write(socketfd, buf, 1024);

    read(socketfd, buf, len);
}



Acknowledgements:
http://www.cnblogs.com/skyfsm/p/6287787.html?utm_source=itdadao&utm_medium=referral
http://blog.csdn.net/hairetz/article/details/17968383

2017.09.24

你可能感兴趣的:(网络编程)