1. udp 的 connect 函数什么?UDP 也有 conenct?connect 不是用于 TCP 编程的吗?是的,UDP 网络编程中的确有 connect 函数,但它仅仅用于表示确定了另一方的地址,并没有其他含义。有了以上认识后,我们可以知道 UDP 套接字有以下区分:1)未连接的 UDP 套接字 2)已连接的 UDP 套接字对于未连接的套接字,也就是我们常用的的 UDP 套接字,我们使用的是 sendto/recvfrom 进行信息的收发,目标主机的 IP 和端口是在调用 sendto/recvfrom 时确定的;在一个未连接的 UDP 套接字上给两个数据报调用 sendto 函数内核将执行以下六个步骤:1)连接套接字 2)输出第一个数据报 3)断开套接字连接 4)连接套接字 5)输出第二个数据报 6)断开套接字连接对于已连接的 UDP 套接字,必须先经过 connect 来向目标服务器进行指定,然后调用 read/write 进行信息的收发,目标主机的 IP 和端口是在 connect 时确定的,也就是说,一旦 conenct 成功,我们就只能对该主机进行收发信息了。已连接的 UDP 套接字给两个数据报调用 write 函数内核将执行以下三个步骤:1)连接套接字 2)输出第一个数据报 3)输出第二个数据报由此可以知道,当应用进程知道给同一个目的地址的端口号发送多个数据报时,显示套接字效率更高。下面给出带 connect 函数的 UDP 通信框架
具体框架代码不再给出了,因为跟上面不带 connect 的代码大同小异,仅仅多出一个 connect 函数处理而已,下面给出处理 conenct() 的基本步骤。
- void udp_handler(int s, struct sockaddr* to)
- {
- char buf[1024] = "TEST UDP !";
- int n = 0;
- connect(s, to, sizeof(*to);
- n = write(s, buf, 1024);
- read(s, buf, n);
- }
2. udp 报文丢失问题因为 UDP 自身的特点,决定了 UDP 会相对于 TCP 存在一些难以解决的问题。第一个就是 UDP 报文缺失问题。在 UDP 服务器客户端的例子中,如果客户端发送的数据丢失,服务器会一直等待,直到客户端的合法数据过来。如果服务器的响应在中间被路由丢弃,则客户端会一直阻塞,直到服务器数据过来。防止这样的永久阻塞的一般方法是给客户的 recvfrom 调用设置一个超时,大概有这么两种方法:1)使用信号 SIGALRM 为 recvfrom 设置超时。首先我们为 SIGALARM 建立一个信号处理函数,并在每次调用前通过 alarm 设置一个 5 秒的超时。如果 recvfrom 被我们的信号处理函数中断了,那就超时重发信息;若正常读到数据了,就关闭报警时钟并继续进行下去。2)使用 select 为 recvfrom 设置超时设置 select 函数的第五个参数即可。
3. udp 报文乱序问题所谓乱序就是发送数据的顺序和接收数据的顺序不一致,例如发送数据的顺序为 A、B、C,但是接收到的数据顺序却为:A、C、B。产生这个问题的原因在于,每个数据报走的路由并不一样,有的路由顺畅,有的却拥塞,这导致每个数据报到达目的地的顺序就不一样了。UDP 协议并不保证数据报的按序接收。解决这个问题的方法就是发送端在发送数据时加入数据报序号,这样接收端接收到报文后可以先检查数据报的序号,并将它们按序排队,形成有序的数据报。
4. udp 流量控制问题总所周知,TCP 有滑动窗口进行流量控制和拥塞控制,反观 UDP 因为其特点无法做到。UDP 接收数据时直接将数据放进缓冲区内,如果用户没有及时将缓冲区的内容复制出来放好的话,后面的到来的数据会接着往缓冲区放,当缓冲区满时,后来的到的数据就会覆盖先来的数据而造成数据丢失(因为内核使用的 UDP 缓冲区是环形缓冲区)。因此,一旦发送方在某个时间点爆发性发送消息,接收方将因为来不及接收而发生信息丢失。解决方法一般采用增大 UDP 缓冲区,使得接收方的接收能力大于发送方的发送能力。
int n = 220 * 1024; //220kB
setsocketopt(sockfd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)); 这样我们就把接收方的接收队列扩大了,从而尽量避免丢失数据的发生。参考书目:《UNIX 网络编程卷 1》《Linux 网络编程》《嵌入式 Linux 软件开发从入门到精通》来源: http://www.bubuko.com/infodetail-2131429.html