前一篇文章介绍了linux网络编程中的TCP编程:http://blog.csdn.net/andoubi/article/details/51778988,本文主要介绍UDP编程。
UDP编程模型如下图所示:
与TCP传输数据相比,UDP传输数据前不需要建立连接。
1、具体用到的函数如下:
服务器端:
创建socket: socket() 绑定地址:bind() 发/收数据:sendto()/recvfrom() 结束连接:close()
客户机端:
创建socket: socket() 发/收数据:sendto()/recvfrom() 结束连接:close()
2、涉及函数详解:
与TCP编程相比,UDP编程知识数据的发送接收函数有变化,其它函数都是一样的。这里就介绍一些数据的发送接收函数。
2.1数据发送函数:sendto函数
destaddr是接收端套接字的地址。使用sendto函数发送数据,必须指定接收端套接字地址。在TCP编程中,send函数不需要指定地址,因为目标地址暗含在连接中了。
2.2数据接收函数:recvfrom函数
addr用来存储数据发送端套接字的地址。recvfrom函数在接收数据的同时也获取了发送端套接字地址。而在TCP编程中,是通过accept函数来获取与服务器建立连接的套接字地址。
3、实例(这些代码都是跟着国嵌的视频课程编写的,都是比较简单的功能)
编写一个UDP服务器程序和客户端程序,实现功能是:在客户端通过键盘输入一些字符,这些字符会发送到服务器,并在服务器上打印出来。
服务器端程序:
#include
#include
#include
#include
#include
#include
#define portnum 123//定义一个端口号
#define MSG_SIZE 128
int main()
{
int sockfd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
char buffer[MSG_SIZE];
int addr_len , n ;//地址长度
//1 创建套接字
if((sockfd=socket( AF_INET, SOCK_DGRAM, 0)) == -1)//如果创建套接字失败
{
printf("create socket error!\n");
exit(1);
}
//2.1 初始化地址
bzero(&server_addr, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons( portnum);//转换成网络字节序
server_addr.sin_addr.s_addr = htonl(INADDR_ANY );//INADDR_ANY:接收任何消息,转换成网络字节序
//2.2 绑定地址
bind( sockfd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr) );
//3 接收数据
while(1)
{
addr_len = sizeof(struct sockaddr);
bzero(buffer, sizeof(buffer));//每次接收前,现将buffer清空
n = recvfrom(sockfd, buffer, MSG_SIZE, 0,(struct sockaddr *)&client_addr,&addr_len);
//打印出客户机地址
printf("Receive data from:%s\n", (inet_ntoa(client_addr.sin_addr)) );
buffer[n] = '\0';
printf("server receive: %s\n", buffer);
}
//4 结束连接
close(sockfd );
return 0 ;
}
客户端程序:(运行程序时,需要指定服务器地址)
#include
#include
#include
#include
#include
#include
#define BUF_SIZE 128
#define PORT 123//端口必须与服务器一样
int main( int argc, char **argv)
{
int sockfd;
char buffer[BUF_SIZE];
struct sockaddr_in server_addr;
if(argc!=2)//如果输入的包含命令名称在内的数据 !=2
{
printf("Usage: %s server_ip\n", argv[0]);
exit(1);
}
//1 创建套接字
if((sockfd=socket( AF_INET, SOCK_DGRAM, 0)) == -1)//如果创建套接字失败
{
printf("create socket error!\n");
exit(1);
}
//服务器地址初始化
bzero(&server_addr, sizeof(struct sockaddr_in));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons( PORT);//转换成网络字节序
inet_aton(argv[1],&server_addr.sin_addr);//将键盘输入的字符串格式地址,转化成整型IP
//2 发送数据
while(1)
{
printf("Please input char:\n");
fgets( buffer, BUF_SIZE,stdin);
sendto(sockfd,buffer,strlen(buffer),0,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr));
bzero(buffer,BUF_SIZE );//每次发送完,将buffer清空
}
//3关闭连接
close( sockfd);
}
对比:
TCP协议(传输控制协议)和UDP协议(用户数据报协议)的区别之一是:前者是面向链接的协议,后者是无连接协议。若要使用TCP来传输数据,则传输数据之前,客户端与服务器必须先建立连接。而使用UDP传输数据则不需要建立连接,只需要事先确定数据接收端套接字的地址。相比而言,使用TCP来传输数据要可靠的多。这里有一个简单的比喻来说明TCP和UDP传输数据的差异:
用UDP传输数据相当于给某人邮寄信件。虽然可以邮寄很多信件,但是无法保证信件的投递次序,且在邮递过程中有可能会丢失一些信件。每封信都写有收件人的地址,且没封信可能到达不同的接收者。
用TCP传输数据相当于给某人打电话。首先要通过电话建立一个连接,然后才能彼此双向通信。只有先接通电话才能聊天嘛。建立的每个连接都是端到端的通信通道。会话中不包含地址信息,就像呼叫的两端存在一个点对点的虚拟连接,并且连接本身暗含特定的源和目的地。
参考资料:《UNIX环境高级编程》