面试复习—网络知识点-----UDP
一个UDP程序实例
与tcp程序不同的是,此处无连接,所以也不需要listen创建监听套接字,直接recvfrom接收数据,sendto发送数据
这两个函数原型:
ssize_t recvfrom(int sockfd, void* buff, size_t nbytes, int flags, struct sockaddr* from, len_t* len);
ssize_t sendto(int sockfd, void* buff, size_t nbytes, int flags, struct sockaddr* to, len_t len);
sockfd、buff、nbytes分别代表描述符,指向读出或写入的缓冲区,读写字节数
to代表要发往的接受者地址(自己填写目的地)
from保存发送者的地址(函数返回源)
客户端
①sockfd = socket(AF_INET, SOCK_DGRAM, 0);
SOCK_DGRAM代表数据报套接字
②struct sockaddr_in servaddr;//声明一个网际套接字地址结构
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);//绑定服务器端口
inet_pton(AF_INET, argv[1], &servaddr.sin_addr);//绑定服务器ip地址(先将点分十进制数串转换成32位二进制)
在一个循环中调用③④
③sendto(sockfd, buff, strlen(buff), 0, (SA*) &servaddr, sizeof(servaddr));
将Buff中的内容发送给servaddr指定的服务器
④n =recvfrom(sockfd, recvline, MAXLINE, 0,NULL,NULL); //不关心谁发送的,可以将后两个参数置空
使用recvline保存recvfrom返回的结果
⑤调用exit(0)
服务器
①sockfd = socket(AF_INET, SOCK_DGRAM, 0);
②struct sockaddr_in servaddr, cliaddr;;//声明两个网际套接字地址结构
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);//绑定服务器端口
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
③bind(sockfd, (SA *)&servaddr, sizeof(servaddr));
在一个循环中调用④⑤
④n = recvfrom(sockfd, recvline, MAXLINE, 0, (SA *)&cliaddr, sizeof(cliaddr));
读取请求信息。使用cliaddr保存发送者地址,因为sendto要用。
⑤sendto(sockfd, buff, strlen(buff), 0,(SA *)&cliaddr, sizeof(cliaddr));//将反馈信息发送给客户端
(1)其实,在UDP客户端中,也可以调用connect函数,只不过和TCP不同,这个时候不在发起三次握手,而只是检测目的是否可达等有没有明显的立即可知的错误。调用connect之后,就可以不必sendto和recvfrom了,直接write和read即可。自动发送给connect的目标协议地址。(多次调用的目的:①指定新的端口②断开已连接)
应用场景:当应用进程知道要给同一目的地址发送多个数据报的时候,显式调用套接字连接效率比较高!!
(2)UDP无流量控制,所以在请求到达服务端的时候,可能会导致缓冲区满而丢包。
(3)TCP可以检测丢失的分组并且重传,验证响应是否来自正确的对端。udp没有自动验证,可以手动验证。