UDP 提供的是无连接、不可靠的、数据报服务。服务器端和客户端没有什么本质上的区别。编程流程如下:
服务器端代码ser.c如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{ //1.创建套接字
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)
{
printf("创建失败");
exit(1);
}
struct sockaddr_in saddr,caddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(6000);
saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
//2.指定套接字的地址,绑定ip和端口
int res=bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
if(res==-1)
{
printf("绑定失败");
exit(1);
}
int len=sizeof(caddr);
while(1)
{
char buff[128]={0};
//3.接收客户端的消息,谁发来数据就接收谁的数据,并没有和任何客户端建立连接
recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);
//客户端的信息(ip和端口)存放到caddr,caddr指定数据的来源,中记录着是谁发的数据
printf("buff(%d)=%s\n",ntohs(caddr.sin_port),buff);
//4.向客户端回复数据
sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));
}
}
客户端代码cli.c如下:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
//1.创建套接字
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(sockfd==-1)
{
printf("创建失败");
exit(1);
}
struct sockaddr_in saddr;//服务器的地址,ip和端口
memset(&saddr,0,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(6000);
saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
int len =sizeof(saddr);
while(1)
{
char buff[128]={0};
printf("输入数据:");
fgets(buff,128,stdin);
if(strncmp(buff,"end",3)==0)
{
break;
}
//2.向服务器端发送数据
sendto(sockfd,buff,sizeof(buff),0,(struct sockaddr*)&saddr,sizeof(saddr));
memset(buff,0,sizeof(buff));
//3.接收服务器端回复的数据
recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);
printf("buff=%s\n",buff);
}
//4.关闭套接字
close(sockfd);
}
运行结果:
从结果可以看出,当服务器端启动之后,可以同时启动多个客户端与客户端通信,但是两个客户端的端口号是不同的。
将服务器端关闭再重启后,客户端依旧可以与服务器端通信,如下图所示:
如果服务器端关闭后,客户端向服务器端发送数据就会发生阻塞,阻塞在客户端的recvfrom这个地方,因为服务器没启动,端口没有人使用,那么数据就会被丢掉,所以没有服务器端给客户端回复数据,所以就会阻塞在recvfrom这个地方。如下图:
此时客户端代码cli.c执行完了sendto,接下来执行recvfrom的时候就被阻塞住了,因为没有服务器端给客户端回复消息,此时发送的aaaaaa发给本主机的6000端口,但是本主机的6000端口没有被占用,也就是6000端口没有被使用,所以所发送的数据aaaaaa就直接被丢掉了,所以也不会有服务器端给客户端回复消息,客户端就会在recvfrom这个地方阻塞住。
将服务器端代码ser.c中的recvfrom那一行的代码修改为如下情况,让服务器端一次只收一个字符:
recvfrom(sockfd,buff,1,0,(struct sockaddr*)&caddr,&len);
此时的运行结果:
因篇幅问题不能全部显示,请点此查看更多更全内容