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

news/2024/10/17 20:18:19/

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);
}

tcp和udp的使用区别

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

所有源码下载点这~~


http://www.ppmy.cn/news/274036.html

相关文章

谷粒商城-分布式基础篇2

1 三级分类 1.1 sql脚本 DROP TABLE IF EXISTS pms_category;CREATE TABLE pms_category (cat_id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 分类id,name char(50) DEFAULT NULL COMMENT 分类名称,parent_cid bigint(20) DEFAULT NULL COMMENT 父分类id,cat_level int(11)…

计算机基础

计算机(computer)俗称电脑,是一种用于高速计算的电子计算机器,可以进行数值计算,又可以进行逻辑计算,还具有存储记忆功能。是能够按照程序运行,自动、高速处理海量数据的现代化智能电子设备。由…

计算机硬件从门外到入门(计算机知识科普)

计算机硬件从门外到入门(计算机知识科普) 计算机是什么计算机的分类超级计算机网络计算机1、服务器2、工作站3、集线器4、交换机5、路由器 工业控制计算机1、IPC2、可编程序控制器(PLC)3、分散型控制系统(DCS&#xff…

这个博客必须转

原文地址:  http://blog.csdn.net/leezy_2000/article/details/38798117 程序员生存定律这系列的目录在这里:程序员生存定律--目录 喜欢从头瞄的,可以移步。 -----------------------------------------------------…

程序员生存定律-六个程序员的故事(2) .

程序员生存定律这系列的目录在这里:程序员生存定律--目录 喜欢从头瞄的,可以移步。 ------------------------------------------------------------------------------- 一个关于项目经理的故事 1 项目经理的养成日记 L在2001年毕业之后加入到了福建…

程序员生存定律-六个程序员的故事(2)

程序员生存定律这系列的目录在这里:程序员生存定律--目录喜欢从头瞄的,可以移步。------------------------------------------------------------------------------- 一个关于项目经理的故事 1 项目经理的养成日记 L在2001年毕业之后加入到了福建实…

程序员生存定律

原文地址:http://blog.csdn.net/leezy_2000/article/details/29407747#comments 关于作者的各种信息,在上面可找到,想了解下写这书的人是不是骗子和大忽悠的可以瞄。 最后希望感兴趣的支持 V众投 ,感觉上这应该是国内最靠谱的…

程序人生

转载地址:http://blog.csdn.net/leezy_2000/article/details/38798117 首先吐槽下,csdn竟然没有一键转载的功能,不得不说这个很有点问题。最坑爹的是它能转到其他社区去,真是专门利人,毫不利己。希望什么时候能够增加…