UDP(User Datagram Protocol)是无连接不可靠的数据报协议。使用的UDP的常用应用有:DNS、NFS、SNMP、tftp等。
典型的UDP客户-服务器程序
#include <sys/socket.h>
ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags,
const struct sockaddr *addr, socklen_t addrlen);
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sendto的最后两个参数类似于connect的最后两个参数:调用时其中套接字地址结构被我们填入数据报将发往(UDP)或与之建立连接(TCP)的协议地址。
ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags,
struct sockaddr *addr, socklen_t *addrlen);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
recvfrom的最后两个参数类似于accept的最后两个参数:返回时其中套接字地址结构的内容告诉我们是谁发送了数据报(UDP)或是谁发起了连接(TCP)。
(1)UDP层中隐含有排队发生。事实上每个UDP套接字都有一个接收缓冲区,到达该套接字的每个数据报都进入这个套接字接收缓冲区。当进程调用recvfrom时,缓冲区中的下一个数据报以FIFO顺序返回给进程。然而这个缓冲区的大小是有限的。(可以通过SO_RCVBUF进行设置)
(2)知道客户临时端口号的任何进程(无论是与本客户进程相同的主机上还是不同的主机上)都可以向该客户发送数据报,而且这些数据报会与正常的服务器应答混杂。(参见例一)
(3)UDP没有流量控制并且是不可靠的。
一般来说,大多数TCP服务器是并发的,而大多数UDP服务器是迭代的。
例一:
/* 客户端代码 */
#include "../myunp.h"
void UdpClient(int sockfd, const struct sockaddr *pservaddr, socklen_t servlen)
{
int n = 0;
char sendline[MAXLINE] = {0};
char recvline[MAXLINE + 1] = {0};
socklen_t len = 0;
struct sockaddr *preplyaddr = NULL;
while (fgets(sendline, MAXLINE, stdin) != NULL) {
if (sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen) < 0) {
printf("sendto error: %s\n", strerror(errno));
return;
}
len = servlen;
if ((n = recvfrom(sockfd, recvline, MAXLINE, 0, preplyaddr, &len)) < 0) {
printf("recvfrom error: %s\n", strerror(errno));
return;
}
recvline[n] = 0; /* null terminate */
fputs(recvline, stdout);
}
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
if (argc != 2) {
printf("usage: udpcli <IP address>");
return -1;
}
memset(&servaddr, '\0', sizeof(servaddr));
servaddr.sin_family