UDP编程函数recvfrom()、inet_pton()、sendto()
- UDP协议 user data protrol 用户数据协议特点:
TCP: 面向连接 --> 一定双方连接上了才能进行通信!
UDP: 面向非连接 --> 不需要连接就可以进行数据的收发,提高效率。
UDP例子: 写信
- UDP实现过程
例题: 客户端发送数据给服务器,使用UDP完成。
服务器:(收信) Rose.c
(1). 买一个信箱
int fd = socket(AF_INET,SOCK_DGRAM,0);
(2). 绑定一个地址到信箱
struct sockaddr_in srvaddr;
srvaddr.sin_family = AF_INET; //协议
srvaddr.sin_port = htons(atoi(argv[1])); //端口号
srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址
bind(fd,(struct sockaddr *)&srvaddr,len);
(3). 不断收信
recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *)&cliaddr,&len);
(4). 销毁信箱
close(fd);
客户端:(写信)
(1). 买一个信箱
int fd = socket(AF_INET,SOCK_DGRAM,0);
(2). 准备服务器地址
struct sockaddr_in srvaddr;
socklen_t len = sizeof(srvaddr);
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET,argv[1],&srvaddr.sin_addr);
(3). 不断往服务器地址写信
sendto(fd,buf,strlen(buf),0,(struct sockaddr *)&srvaddr,len);
(4). 销毁信箱
close(fd);
例子:
Jack.c
备注:本次测试为Linux Ubuntu18.04系统,更新原文章头文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <arpa/inet.h>
int main(int argc,char *argv[]) // ./Jack 192.168.0.243 50002
{
//1. 创建UDP套接字(没有地址的信箱)
int fd = socket(AF_INET,SOCK_DGRAM,0);
//2. 准备服务器的地址
struct sockaddr_in srvaddr;
socklen_t len = sizeof(srvaddr);
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(atoi(argv[2]));
inet_pton(AF_INET,argv[1],&srvaddr.sin_addr);
//AF_INET: 协议,与socket第一个参数一致
//argv[1]: 代表一个字符串,"192.168.0.243"
//&srvaddr.sin_addr: 代表struct in_addr *类型,使用srvaddr变量访问sin_addr这个变量,再取地址就变成指针了!
/*
struct sockaddr_in
{
u_short sin_family; // 地址族
u_short sin_port; // 端口
struct in_addr sin_addr; // IPV4地址
char sin_zero[8];
};
*/
//3. 不断写信
char buf[50];
while(1)
{
bzero(buf,50);
fgets(buf,50,stdin);
sendto(fd,buf,strlen(buf),0,(struct sockaddr *)&srvaddr,len);
if(strncmp(buf,"quit",4) == 0)
break;
}
//4. 回收套接字资源
close(fd);
return 0;
}
Rose.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
int main(int argc,char *argv[]) // ./Rose 50001
{
//1. 创建UDP套接字(没有地址的信箱)
int fd = socket(AF_INET,SOCK_DGRAM,0);
//2. 准备服务器的IP地址(准备地址)
struct sockaddr_in srvaddr;
socklen_t len = sizeof(srvaddr);
bzero(&srvaddr,len);
srvaddr.sin_family = AF_INET; //协议
srvaddr.sin_port = htons(atoi(argv[1])); //端口号
srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址
//3. 绑定地址到套接字(把准备好的地址绑定到信箱上)
bind(fd,(struct sockaddr *)&srvaddr,len);
//4. 不断从UDP套接字中接收数据
struct sockaddr_in cliaddr;
char buf[50];
while(1)
{
bzero(buf,50);
//不断从fd这个信箱上读取cliaddr这个客户端给我发来的内容,然后存放在buf中
recvfrom(fd,buf,sizeof(buf),0,(struct sockaddr *)&cliaddr,&len);
printf("from Jack:%s",buf);
if(strncmp(buf,"quit",4) == 0)
break;
}
//5. 关闭套接字资源
close(fd);
return 0;
}
运行步骤:
同桌Ubuntu 你的Ubuntu
Rose.c Jack.c
192.168.0.10 192.168.0.20
50001 50001
同桌: ping 192.168.0.20
你: ping 192.168.0.10
同桌: ./Rose 50001
你: ./Jack 192.168.0.10 50001