特点
UDP 即用户数据报协议,它是一种无连接协议,因此不需要像 TCP 那样通过三次握手来建立一个连接。同时,一个 UDP 应用可同时作为应用的客户或服务器方。由于 UDP 协议并不需要建立一个明确的连接,因此建立 UDP 应用要比建立 TCP 应用简单得多。
UDP和TCP协议的比较
(1)对数据可靠性的要求
对数据要求高可靠性的应用需选择 TCP 协议,如验证、密码字段的传送都是不允许出错的,而对数据的可靠性要求不那么高的应用可选择 UDP 传送。
(2)应用的实时性
由于 TCP 协议在传送过程中要进行三次握手、重传确认等手段来保证数据传输的可靠性。使用 TCP 协议会有较大的时延,因此不适合对实时性要求较高的应用,如 VOIP、视频监控等。相反,UDP 协议则在这些应用中能发挥很好的作用。
(3)网络的可靠性
由于 TCP 协议的提出主要是解决网络的可靠性问题,它通过各种机制来减少错误发生的概率。因此,在网络状况不是很好的情况下需选用 TCP 协议(如在广域网等情况),但是若在网络状况很好的情况下(如局域网等)就不需要再采用 TCP 协议,选择 UDP 协议来减少网络负荷。
UDP协议实例
客户端应用程序
客户端应用程序完成接收终端输入数据,并将其发送至服务器,并接收服务器的数据显示在终端。
#include<stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#define BUF_SIZE 512
/**********************用到的函数*******************************
int socket(int domain, int type, int protocol); 创建套接字
AF_INET IPV4协议 SOCK_STREAM
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
struct sockaddr {
sa_family_t sa_family; //地址族
char sa_data[14]; //14 字节的协议地址,包含该 socket 的 IP 地址和端口号
}
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET
in_port_t sin_port; /* port in network byte order
struct in_addr sin_addr; /* internet address
};
struct in_addr {
uint32_t s_addr; /* address in network byte order
};
int listen(int sockfd, int backlog);
sighandler_t signal(int signum, sighandler_t handler);
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
char *fgets(char *s, int size, FILE *stream);
********************************************************/
int main()
{
int client_id,clientlen;
struct sockaddr_in clientadd;
char buffer[BUF_SIZE];
client_id=socket(AF_INET,SOCK_DGRAM,0); //创建套接字 采用数据报式发送
clientadd.sin_family=AF_INET; //IPV4协议
clientadd.sin_port=htons(9736);//指定端口号
clientadd.sin_addr.s_addr=inet_addr ("192.168.1.121"); //绑定IP地址,采用inet_addr将IP地址转换为需要的数据
memset(buffer,0,strlen(buffer));
printf("please input:");
fgets(buffer,BUF_SIZE,stdin);
//向服务器写
clientlen=sizeof(clientadd);
sendto(client_id,buffer,BUF_SIZE,0,(struct sockaddr *)&clientadd,clientlen);//将接收到的内容发送至服务器
sleep(rand()%3);
memset(buffer,0,strlen(buffer));
recvfrom(client_id,buffer,BUF_SIZE,0,(struct sockaddr *)&clientadd,&clientlen);//接收服务器的数据
printf("You input:%s\n",buffer);
close(client_id);
return 0;
}
服务器端应用程序
#include<stdio.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */
#include <arpa/inet.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#define BUF_SIZE 512
/*****************************************************
int socket(int domain, int type, int protocol); 创建套接字
AF_INET IPV4协议 SOCK_STREAM
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
struct sockaddr {
sa_family_t sa_family;
char sa_data[14];
}
struct sockaddr_in {
sa_family_t sin_family; /* address family: AF_INET
in_port_t sin_port; /* port in network byte order
struct in_addr sin_addr; /* internet address
};
struct in_addr {
uint32_t s_addr; /* address in network byte order
};
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
********************************************************/
int main()
{
int socket_id,client_id;
struct sockaddr_in serveradd;
struct sockaddr_in clientadd;
int clientlen;
char buffer[BUF_SIZE+1];
int recvbyte;
socket_id=socket(AF_INET,SOCK_DGRAM,0); //创建套接字 数据报
serveradd.sin_family=AF_INET;//IPV4 协议
serveradd.sin_port=htons(9736);//指定端口号
serveradd.sin_addr.s_addr=htonl(INADDR_ANY); //绑定IP地址
//将服务器端的绑定要监控的端口号和IP地址
if(bind(socket_id,(struct sockaddr *)&serveradd,sizeof(serveradd))==-1)
{
//绑定失败
printf("connect failed!\n");
exit(EXIT_FAILURE);
}
signal(SIGCHLD,SIG_IGN);
memset(buffer,0,strlen(buffer));
while(1)
{
clientlen=sizeof(clientadd);
printf("please waiting....\n");
recvbyte=recvfrom(socket_id,buffer,BUF_SIZE,0,(struct sockaddr *)&clientadd,&clientlen);//接收客户端发送的数据
if(fork()==0)//新建子进程用于处理接收到的数据
{
printf("You input :%s\n",buffer);
sendto(socket_id,buffer,BUF_SIZE,0,(struct sockaddr *)&clientadd,clientlen);
memset(buffer,0,strlen(buffer));
exit(EXIT_SUCCESS);
}
}
close(socket_id);//关闭子进程
return 0;
}