网络编程(学习)2024.9.3
目录
UDP多点通信
广播
理论
发送端--相当于udp客户端
接收端--相当于udp服务器
组播
理论
发送端
接收端
UDP多点通信
广播
理论
前面介绍的数据包发送方式只有一个接受方,称为单播
如果同时发给局域网中的所有主机,称为广播
只有用户数据报(使用UDP协议)套接字才能广播
一般被设计成局域网搜索协议
广播地址:以192.168.1.0 (255.255.255.0) 网段为例,最大的主机地址192.168.1.255代表该网段的广播地址
发到该地址的数据包被所有的主机接收
发送端--相当于udp客户端
1.socket;
2.setsockopt 允许发送广播
3.填充结构体
a.IP:广播地址
b.端口号,应该与接收端的端口号
4.发送广播
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
// 1.创建套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("创建套接字失败\n");
return -1;
}
// 2.允许发送广播
int flag = 1;
socklen_t len = sizeof(flag);
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &flag, len);
// 3.填充结构体
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
saddr.sin_addr.s_addr = inet_addr("192.168.50.255");
socklen_t addrlen = sizeof(saddr);
#define N 64
char buf[N];
while (1)
{
memset(buf, 0, N);
printf("请输入要输入的数据:");
scanf("%s", buf);
getchar();
sendto(sockfd, buf, N, 0, (struct sockaddr *)&saddr, addrlen);
}
close(sockfd);
return 0;
}
接收端--相当于udp服务器
1.socket;
2.填充结构体
a.IP:(0.0.0.0):本机所有可用IP--局域网IP、本地回环、广播地址、已加入的多播组
b.port:端口号 8888
3.bind
4.recvfrom
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
// 1.创建套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("创建套接字失败\n");
return -1;
}
// 2.bind绑定IP和Port端口号
struct sockaddr_in saddr, caddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(atoi(argv[1]));
saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
socklen_t addrlen = sizeof(saddr);
if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
{
perror("bind失败");
return -1;
}
printf("bind成功\n");
// 3.接收消息
#define N 64
char buf[N];
while (1)
{
int ret = recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&caddr, &addrlen);
if (ret < 0)
{
perror("接收消息失败\n");
close(sockfd);
return -1;
}
else
{
printf("客户端ip:%s:%s\n", inet_ntoa(caddr.sin_addr), buf);
}
}
close(sockfd);
return 0;
}
组播
理论
接收方是局域网里的一部分
好处:避免了像广播那样带来的比较大的网络负载组播地址:224.0.0.1~~239.255.255.254
发送端
1、socket;
2、填充结构体
a)IP:组播IP
b)port
3、发送
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
// 1.创建套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("创建套接字失败\n");
return -1;
}
//2.填充结构体
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
saddr.sin_addr.s_addr = inet_addr("224.0.0.3");
socklen_t addrlen = sizeof(saddr);
#define N 64
char buf[N];
while (1)
{
memset(buf, 0, N);
printf("请输入要输入的数据:");
scanf("%s", buf);
getchar();
sendto(sockfd, buf, N, 0, (struct sockaddr *)&saddr, addrlen);
}
close(sockfd);
return 0;
}
接收端
1、socket
2、setsockopt 加入多播组
3、填充结构体
a)ip:0.0.0.0
b)PORT
4、bind
5、recvfrom
关于setsockopt要填充的结构体
struct ip_mreq
{
struct in_addr imr_multiaddr; /* 指定多播组IP */
struct in_addr imr_interface; /* 本地网卡地址,通常指定为 INADDR_ANY--0.0.0.0*/};
}struct ip_mreq mreq;
//bzero(&mreq, sizeof(mreq));
mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.1");
mreq.imr_interface.s_addr = INADDR_ANY;
setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
// 1.创建套接字
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
perror("创建套接字失败\n");
return -1;
}
// 加入多播组
struct ip_mreq mreq;
// bzero(&mreq, sizeof(mreq));
mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.3");
mreq.imr_interface.s_addr = INADDR_ANY;
setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
struct sockaddr_in saddr, caddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(atoi(argv[1]));
saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
socklen_t addrlen = sizeof(saddr);
if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
{
perror("bind失败");
return -1;
}
printf("bind成功\n");
// 3.接收消息
#define N 64
char buf[N];
while (1)
{
int ret = recvfrom(sockfd, buf, N, 0, (struct sockaddr *)&caddr, &addrlen);
if (ret < 0)
{
perror("接收消息失败\n");
close(sockfd);
return -1;
}
else
{
printf("客户端ip:%s:%s\n", inet_ntoa(caddr.sin_addr), buf);
}
}
close(sockfd);
return 0;
}