UDP:面向无连接,不安全,不可靠的,没有状态的传输协议
数据报:报文传输(目的方要么整个报文收,要么都不收到)
网络字节序:网络采用统一的字节顺序
htons();将端口转换指定的顺序存储
服务器:接受用户的请求并作响应Server
客户端:向用户发出请求,并等待响应 (知道 IP与端口)
UDP:C/S
客户端 服务器端
1、创建套接字 1、创建套接字
int socket(协议族,转输方式,默认0); int socket(协议族,转输方式,默认0);
2、发送信息 2、绑定套接字:将地址与端口
sendto bind
3、关闭套接字 3、收/发信息 recv / sendto 4、关闭套接字
地址类型:
1、strurct sockaddr
{
unsigned short sa_family;//地址族
char sa_data[14]; //地址和端口号
}; struct sockaddr_in
{
unsigned short sa_fafily;
unsigned short sa_port;//端口号
struct in_addr sin_addr;/*IP地址*/
unsigned char sin_zeron[8];//填充0(没有意义)
};
注:先打开服务器
相关API:
1、创建套接字
socket
2、绑定套接字
bind
3、套接字地址类型:
struct sockaddr_in
{
};
4、转换网张字节序:
htons(short);
inet_addr(char* ip);
5、接收
recv(int ,void* ,size_t,int flag); //只接收内容
recvfrom(int,void*,size_t,int flog,struct sockaddr*,int*); //接收内容并接收IP 6、将网络字节顺序的IP地址转换为字符串(4段点分十进制) char *inet_ntoa(struct in_addr in);
用户层协议:双方约定的规则
语法 语义
1#1 关机 注:在网络中,接收信息的函数为阻塞函数(当没有信息来时,则阻塞。)
UDP 的服务器端代码实现 , 实现了客户端发送消息到服务端的功能 :
#include
#include
#include
#include
#include
//服务器i:接受消息
int main()
{
//创建套接字--UDP
int fd=socket(AF_INET,SOCK_DGRAM,0);
if(fd<0)
{
perror("socket fail");
return -1;
}
//绑定套接字:用于指明套接字绑定的网卡和端口号
struct sockaddr_in addr;
//将地址结构体清空为0
bzero(&addr,sizeof(addr));
addr.sin_family =AF_INET; //指定该地址为IPV4
addr.sin_port =htons(7979);//端口
addr.sin_addr.s_addr =inet_addr("192.168.X.XXX");//本机的网卡IP地址为:XXX
if(-1==bind(fd,(struct sockaddr*)&addr,sizeof(addr)))
{
perror("bind");
return -1;
}
//3收发消息
char buf[100]="";
int ilen=-1;
while((ilen=recv(fd,buf,100,0))>0)
{
buf[ilen]='\0';
printf("收到内容:%s\n",buf);
}
//4关闭消息
close(fd);
}
客户端的代码实现 :
#include
#include
#include
#include
#include
int main()
{
//创建套接字:
int fd=socket(AF_INET,SOCK_DGRAM,0);
//绑定套接字:
//3发送
struct sockaddr_in addr;
addr.sin_family =AF_INET;//地址
addr.sin_port =htons(7979);
addr.sin_addr.s_addr =inet_addr("192.168.X.XXX");
char buf[10]="";
scanf("%s",buf);
sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&addr,sizeof(addr));
//关闭
close(fd);
}
UDP 的服务器端代码实现 , 实现了客户端发送消息到服务端 , 并且服务端返回消息给客户端 , 客户端接收服务端消息的功能 :
#include
#include
#include
#include
#include
//服务器:接受请求,并响应请求
int main()
{
//1创建套接字:
int fd=socket(AF_INET,SOCK_DGRAM,0);
if(fd<0)
{
perror("socket fail");
return -1;
}
//2绑定IP地址和端口号
struct sockaddr_in addr;
bzero(&addr,sizeof(addr));
addr.sin_family =AF_INET;
addr.sin_port =htons(7979);
addr.sin_addr.s_addr =INADDR_ANY;//本机地址
if(bind(fd,(struct sockaddr*)&addr,sizeof(addr))<0)
{
perror("bind fail");
return -1;
}
//3收消息
char buf[1024]="";
int ilen=0;
//地址类型
struct sockaddr_in caddr;
int addlen=sizeof(caddr);
while(1)
{
//ilen=recv(fd,buf,1023,0);
ilen=recvfrom(fd,buf,1023,0,(struct sockaddr*)&caddr,&addlen);
if(ilen<=0)//接收失败
break;
//添加结束字符
buf[ilen]='\0';
printf("(%s:%d):%s\n",inet_ntoa(caddr.sin_addr),\
caddr.sin_port, \
buf); \
//解析字符串:
if(strcmp(buf,"1#1")==0)
{
printf("客户端让我关机\n");
//返回状态:
//发关送信息
sendto(fd,"ok",2,0,(struct sockaddr*)&caddr,addlen);
}
}
//4关闭
close(fd);
}
客户端的代码实现 :
#include
#include
#include
#include
#include
//客户端:
int main()
{
//1创建套接字
int fd=socket(AF_INET,SOCK_DGRAM,0);
char buf[100]="";
//[2绑定套接字:
int pid=fork();
if(pid>0)//父进程---发送信息
{
//3发送
struct sockaddr_in addr;
addr.sin_family =AF_INET;//地址
addr.sin_port =htons(7979);
addr.sin_addr.s_addr =inet_addr("192.168.8.216");
while(1)
{
scanf("%s",buf);//等待输入(阻塞)
if(sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&addr,sizeof(addr))<=0)
break;//发送失败
}
//等待子进程结束
wait(NULL);
}
else if(pid==0)//子进程---接收信息
{
int ilen=0;
while(1)
{
ilen=recv(fd,buf,99,0);
if(ilen<=0)
break;
//添加结尾
buf[ilen]='\0';
printf("收到:%s\n",buf);
}
}
else
{
perror("fork fail");
return -1;
}
//4关闭
close(fd);
}