UDP与TCP相比,各有优缺点,下来来列举一下UDP的缺点:
1.UDP是一种不可靠的协议(缺乏流量控制)
实例代码:
//server.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main()
{
int sockfd;
struct sockaddr_in servaddr,clientaddr;
char recv[1024];
socklen_t len;
int count = 0;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset(&servaddr, '\0', sizeof(servaddr));
memset(recv, '\0', 1024);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons( 5000 );
bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
for( ; ; )
{
recvfrom(sockfd, recv, 1024, 0, (struct sockaddr *)&clientaddr, &len);
memset(recv, '\0', 1024);
count++;
printf("count = %d\n",count);
}
close(sockfd);
}
//client.c
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
int sockfd;
struct sockaddr_in servaddr;
char buff[1024];
int count = 0;
memset(&servaddr, '\0', sizeof(servaddr));
memset(buff, '\0', 1024);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons( 5000 );
servaddr.sin_addr.s_addr = inet_addr("192.168.59.129");
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
for(count; count < 4000; count++)
{
sendto(sockfd, buff, 1024, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
}
close(sockfd);
return 0;
}
客户端快速给服务器发送4000个数据报,然后在服务器端统计接收到的数据报的个数,发现接收到的数据报数量小于4000,这是由于UDP并不是一种可靠的协议,一旦发生丢包等情况,没有重发等机制来应对这种情况。上面程序中出现的情况主要是由于服务器端的接收区缓冲区溢出导致的,一旦缓冲区溢出,后续的数据报就被丢弃。
针对上面这种情况,我们有两种方式来处理:
1.通过socket选项来修改接收缓冲区的大小,以容纳更多的数据报(通过setsockopt函数来设置)
2.发送端每次发送一个数据报以后,暂停一段时间(即不要连续发送大量的数据报,可以使用usleep,sleep等函数来挂起进程)
但是上面两种方式只能用来缓解这种丢包的情况,而不能消除,这是UDP本身的机制决定的。
2.UDP是一种无连接协议
由于UDP是无连接的,因此即使服务器端没有程序在运行,客户端仍然可以运行客户端程序:
//client.c
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main()
{
int sockfd;
struct sockaddr_in servaddr;
char recv[1024];
char send[1024];
int len;
memset(&servaddr, '\0', sizeof(servaddr));
memset(recv, '\0', 1024);
memset(send, '\0', 1024);
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons( 5000 );
servaddr.sin_addr.s_addr = inet_addr("192.168.59.129");
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
sendto(sockfd, send, 1024, 0, (struct sockaddr *)&servaddr, sizeof(servaddr));
printf("stop at sendto\n");
recvfrom(sockfd, recv, 1024, 0, (struct sockaddr *)&servaddr, &len);
printf("stop at recvfrom\n");
close(sockfd);
return 0;
}
//client.c
#include <string.h>