[linux_C语言_udp的多种实现方法]

news/2024/5/18 15:13:52 标签: udp, linux, c语言

linux_C语言_udp的多种实现方法

  • 最基本的方式(不用组播不用sigio信号不使能广播属性)
    • 接收端
    • 发送端
  • 使用SIGIO信号的方式(使用sigio信号使用广播使能属性)
    • 服务端
    • 客户端
  • 使用组播模式
    • 服务端
    • 客户端
  • tcp和udp的使用区别
  • 所有源码下载点这~~

最基本的方式(不用组播不用sigio信号不使能广播属性)

接收端

// 1,创建UDP套接字
int fd = Socket(AF_INET, SOCK_DGRAM, 0);

// 2,准备跟AF_INET(即IPv4网络层协议)对应的特定IP+PORT地址结构体
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
bzero(&addr, len);

addr.sin_family = AF_INET;
inet_aton("192.168.45.153", &addr.sin_addr); // 绑定指定的IP,并做了字节序转换
//addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定自动获取的IP好像一般为0.0.0.0
addr.sin_port  = htons(50001);

// 3,绑定地址
Bind(fd, (struct sockaddr *)&addr, len);

// 5,静静地等待对方的信件...
char buf[100];
int flag=0;
while (1)
{
	// 4,准备接受对方的地址信息
	struct sockaddr_in peeraddr;
	len = sizeof(peeraddr);
	bzero(&peeraddr, len);
	bzero(buf, 100);
	if (recvfrom(fd, buf, 100, 0, (struct sockaddr *)&peeraddr, &len) != 0)//此函数用于UDP套接字接受数据
	{
		flag = 1;
	}

	printf("收到【%s:%hu】的信息: %s",
		inet_ntoa(peeraddr.sin_addr),
		ntohs(peeraddr.sin_port),
		buf);

	if (flag == 1)
	{
		sendto(fd, buf, 100, 0, (struct sockaddr *)&peeraddr, len);//此函数用于向UDP套接字发送数据
		flag = 0;
	}
	printf("发送完毕\n");
}

发送端

char buf[100];
// 1,创建UDP套接字
int fd = Socket(AF_INET, SOCK_DGRAM, 0);

struct sockaddr_in addr;
socklen_t len = sizeof(addr);
bzero(&addr, len);

addr.sin_family = AF_INET;
inet_aton("192.168.45.153", &addr.sin_addr); // 绑定指定的IP,并做了字节序转换(字符串转二进制)
// addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定自动获取的IP
addr.sin_port = htons(50001);

while (1)
{
	bzero(buf, 100);
	scanf("%s", buf);
	getchar();
	sendto(fd, buf, 100, 0, (struct sockaddr *)&addr, len);
	printf("发送完毕\n");

	// 4,准备接受对方的地址信息
	struct sockaddr_in peeraddr;
	len = sizeof(peeraddr);
	bzero(&peeraddr, len);

	// 5,静静地等待对方的信件...
	buf[100];
	bzero(buf, 100);
	recvfrom(fd, buf, 100, 0, (struct sockaddr *)&peeraddr, &len);

	printf("收到【%s:%hu】的信息: %s",
		inet_ntoa(peeraddr.sin_addr),//字节序转换(二进制转)
		ntohs(peeraddr.sin_port),
		buf);
}

使用SIGIO信号的方式(使用sigio信号使用广播使能属性)

服务端

注意事项:
因为客户端会使能广播属性向所有地址(255.255.255.255)进行数据发送
所以这里不能特定指定服务器为某网卡ip地址:inet_aton(“192.168.45.153”, &addr.sin_addr);
这会导致客户端那边发送服务器接受数据失败的情况

// 1,创建UDP套接字
fd = Socket(AF_INET, SOCK_DGRAM, 0);

// 2,准备跟AF_INET(即IPv4网络层协议)对应的特定IP+PORT地址结构体
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
bzero(&addr, len);

addr.sin_family = AF_INET;
//inet_aton("x.x.x.x", &addr.sin_addr); // 绑定指定的IP,并做了字节序转换
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 绑定一个本机的任意可用IP
// inet_aton("192.168.45.153", &addr.sin_addr);//这里需要注意使能广播属性后不能指定IP,不然客户端对255.255.255.255广播地址进行数据发送会接受不到统一用INADDR_ANY
addr.sin_port  = htons(50002);

// 3,绑定地址
Bind(fd, (struct sockaddr *)&addr, len);

// 4,用信号的方式来异步地接收各个客户端发来的UDP信息...

// a. 捕捉信号SIGIO
signal(SIGIO, f);

// b. 设置套接字为异步工作模式(即使之收到数据是产生信号SIGIO)
long flag = fcntl(fd, F_GETFL);
flag |= O_ASYNC;
fcntl(fd, F_SETFL, flag);

// c. 指定本进程为信号的属主
fcntl(fd, F_SETOWN, getpid());


// 服务器忙别的事情
int i=0;
while(1)
{
	i++;
	printf("%d\n",i);
	sleep(1);
}
// 准备接受对方的地址信息
struct sockaddr_in peeraddr;
socklen_t len = sizeof(peeraddr);
bzero(&peeraddr, len);

char buf[100];
bzero(buf, 100);
recvfrom(fd, buf, 100, 0, (struct sockaddr *)&peeraddr, &len);	

printf("收到【%s:%hu】的信息: %s",
		inet_ntoa(peeraddr.sin_addr),
		ntohs(peeraddr.sin_port),
		buf);
// 2,准备跟AF_INET(即IPv4网络层协议)对应的特定IP+PORT地址结构体
struct sockaddr_in addr;
len = sizeof(addr);
bzero(&addr, len);

addr.sin_family = AF_INET;
inet_aton("255.255.255.255", &addr.sin_addr); // 准备好客户端的IP
addr.sin_port = htons(ntohs(peeraddr.sin_port)); // 准备好客户端的PORT
// 3,使能广播属性
int on = 1;
Setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

sendto(fd, buf, 100, 0, (struct sockaddr *)&addr, len);

客户端

// 1,创建UDP套接字
int fd = Socket(AF_INET, SOCK_DGRAM, 0);
int ret;
// 2,准备跟AF_INET(即IPv4网络层协议)对应的特定IP+PORT地址结构体
struct sockaddr_in addr;
socklen_t len = sizeof(addr);

// 4,广播消息
char buf[100];

while(1)
{
	bzero(&addr, len);

	addr.sin_family = AF_INET;
	inet_aton("255.255.255.255", &addr.sin_addr); // 准备好服务器的IP
	// inet_aton("192.168.45.153", &addr.sin_addr);
	addr.sin_port = htons(50002); // 准备好服务器的PORT

	// 3,使能广播属性
	int on = 1;
	Setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

	bzero(buf, sizeof(buf));
	fgets(buf,100,stdin);
	ret = sendto(fd, buf, 100, 0, (struct sockaddr *)&addr, len);
	printf("RETURN %d\n",ret);
	// 准备接受对方的地址信息
	struct sockaddr_in peeraddr;
	socklen_t len = sizeof(peeraddr);
	bzero(&peeraddr, len);

	char buf[100];
	bzero(buf, 100);
	recvfrom(fd, buf, 100, 0, (struct sockaddr *)&peeraddr, &len);

	printf("收到【%s:%hu】的信息: %s",
		inet_ntoa(peeraddr.sin_addr),
		ntohs(peeraddr.sin_port),
		buf);
}

使用组播模式

服务端

// 1,创建UDP套接字
int fd = socket(AF_INET, SOCK_DGRAM, 0);

// 2,准备地址结构体
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
bzero(&addr, len);

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port  = htons(atoi(argv[1]));

// 3,绑定地址
bind(fd, (struct sockaddr *)&addr, len);

// 4,使能广播属性
int on = 1;
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

// 5,准备好组播地址结构体
struct sockaddr_in addr2;
socklen_t len2 = sizeof(addr2);
bzero(&addr2, len2);

addr2.sin_family = AF_INET;
addr2.sin_addr.s_addr = inet_addr("224.0.0.100");
addr2.sin_port  = htons(50003);

// 6,静静地等待客户端的数据
char buf[100];
while(1)
{
	struct sockaddr_in peeraddr;
	socklen_t len = sizeof(peeraddr);
	bzero(&peeraddr, len);
	bzero(buf, 100);
	recvfrom(fd, buf, 100, 0, (struct sockaddr *)&peeraddr, &len);

	printf("收到【%s:%hu】的信息: %s",
			inet_ntoa(peeraddr.sin_addr),
			ntohs(peeraddr.sin_port),
			buf);
	// 转发到组播中
	if(sendto(fd, buf, strlen(buf), 0,
			(struct sockaddr *)&addr2, len2) == -1)
	{
		perror("sendto failed");
	}
}

客户端

// 1,创建UDP套接字
fd = socket(AF_INET, SOCK_DGRAM, 0);


// 2,准备存放自身地址的结构体
struct sockaddr_in myaddr;
socklen_t mylen = sizeof(myaddr);
bzero(&myaddr, mylen);

myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port  = htons(50003);

// 3,绑定固定的地址,方便服务器主动给我发数据
bind(fd, (struct sockaddr *)&myaddr, mylen);


// 4,加入指定的多播组
struct ip_mreq m;
bzero(&m, sizeof(m));

m.imr_multiaddr.s_addr =  inet_addr("224.0.0.100");
m.imr_interface.s_addr =  htonl(INADDR_ANY);

setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &m, sizeof(m));


// a. 捕捉信号SIGIO
signal(SIGIO, f);

// b. 设置套接字为异步工作模式(即使之收到数据是产生信号SIGIO)
long flag = fcntl(fd, F_GETFL);
flag |= O_ASYNC;
fcntl(fd, F_SETFL, flag);

// c. 指定本进程为信号的属主
fcntl(fd, F_SETOWN, getpid());


// 5,准备对端服务器的地址结构体
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
bzero(&addr, len);

addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(argv[1]);
addr.sin_port  = htons(atoi(argv[2]));

// 6,不断给服务器发送数据
//    当收到服务器发来的组播消息时,会触发SIGIO
//    继而会使得 fgets() 出错返回
char buf[100];
while(1)
{
	bzero(buf, 100);
	if(fgets(buf, 100, stdin) == NULL)
	{
		perror("fgets failed");
		continue;
	}

	sendto(fd, buf, strlen(buf), 0,
			(struct sockaddr *)&addr, len);
}

udp_333">tcp和udp的使用区别

tcp具有可靠性所以一般用于cmd命令的一些重要信息收发
udp则速度比较快,一般用于数据的发送比如音视频数据

所有源码下载点这~~


http://www.niftyadmin.cn/n/409690.html

相关文章

蓝桥杯算法备考

对象排序 class PII implements Comparable<PII>{int x;int y;public PII(int x,int y){this.xx;this.yy;}// 如果用到对象排序的话public int compareTo(PII o){return Integer.compare(x,o.x);//从小到大排序// return Integer compare(o.x,x); 从大到小排序} }public…

后端——平台登录功能实战

这里写目录标题 一、登录接口设计示意图二、后端设计三、创建用户表四、后端鉴权逻辑五、登录接口实现六、使用 JWT 生成 token七、路由鉴权八、登录与测试用例服务结合九、跨域一、登录接口设计示意图 二、后端设计 三、创建用户表 db=SQLAlchemy(app

儿童睡眠慢波的起源、同步和传播

摘要 目的&#xff1a;使用EEG delta功率(&#xff1c;4Hz)测量的睡眠慢波活动在整个发育过程中发生显著变化&#xff0c;反映了大脑功能和解剖结构的变化。然而&#xff0c;个体慢波特征随年龄的变化尚未被彻底研究。在这里&#xff0c;本研究旨在表征儿童期到成年期的个体慢…

界面控件DevExtreme工具栏 - 拥有全新的自适应模式/弹出窗口

本文涵盖了最近对DevExtreme JavaScript工具栏组件(v22.2)所做的更改&#xff0c;并简要描述了相关的实现细节。 DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff08;包括React&#xff0c;Angular&#xff0c;ASP.NET C…

【云原生-K8s-2】kubeadm搭建k8s高可用集群(三主两从一VIP)完整教程

&#x1f341;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; 文章目录 Kubernetes高可用集群部署准备工作&a…

QGuiApplication类的使用

QCoreApplication介绍 QCoreApplication类是Qt框架中用于创建非GUI应用程序的基础类&#xff0c;它提供了全局的应用程序环境和事件循环。通过该类&#xff0c;我们能够创建一个命令行程序或后台服务&#xff0c;以响应各种输入和产生输出。 QCoreApplication类封装了大量底层…

自由培训师想实现年入百万,你需要5种能力!

哈喽&#xff0c;大家好&#xff0c;我是海哥&#xff0c;知识付费变现创业教练&#xff0c;教育公司培训总监&#xff0c;从事知识付费变现咨询10年&#xff0c;已助力3000人实现知识付费变现。 现在很多培训机构&#xff0c;培训师朋友蠢蠢欲动&#xff0c;计划脱离机构&…

【LeetCode】240. 搜索二维矩阵 II

240. 搜索二维矩阵 II&#xff08;中等&#xff09; 这道题和 74. 搜索二维矩阵 基本一致&#xff0c;可以放在一起做。 方法一&#xff1a;变形的二叉搜索树 思路 这种做法和 74. 搜索二维矩阵完全一致。 我们可以将二维矩阵抽象成「以右上角为根的 BST」&#xff1a; 那…