多点通信、流式域套接字
一、广播
1.1广播的发送端模型:
#include<myhead.h>
#define BEN_IP "192.168.191.129"
#define BEN_PORT 8888
#define PORT 6666
int main(int argc, const char *argv[])
{
int oldfd = socket(AF_INET,SOCK_DGRAM,0);
if(oldfd == -1)
{
perror("socket");
return -1;
}
//设置允许广播
int k = 999;
if(setsockopt(oldfd,SOL_SOCKET,SO_BROADCAST,&k,sizeof(k)) == -1)
{
perror("setsockopt");
return -1;
}
printf("允许广播设置成功\n");
//3、绑定
struct sockaddr_in send = {
.sin_fanily = AF_INET,
.sin_port = htons(BEN_PORT),
.sin_addr.s_addr = inet_addr(BEN_IP)
};
if(bind(oldfd,(struct sockaddr *)&send,sizeof(send)) == -1)
{
perror("bind");
return -1;
}
struct sockaddr_in broadcast = {
.sin_fanily = AF_INET,
.sin_port = htons(PORT), //发送到6666端口
.sin_addr.s_addr = inet_addr(BEN_IP)
};
char buff[1024];
while(1)
{
fgets(buff,sizeof(buff),stdin);
sendto(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&broadcast,sizeof(broadcast));
if(strcmp(buff,"quit") == 0)
{
printf("发送端退出\n");
break;
}
}
close(oldfd);
return 0;
}
1.2广播的接收端模型:
不管要不要都能接收到
二、组播:
2.1组播发送端模型:
#include<myhead.h>
#define IP "192.191.168.129"
#define PORT 6666
int main(int argc, const char *argv[])
{
//1、创建基于UDP的套接字
int oldfd = socket(AF_INET,SOCK_DGRAM,0);
if(oldfd == -1)
{
perror("socket");
return -1;
}
/*
//2、绑定
struct sockaddr_in send = {
.sin_family = AF_INET,
.sin_port = htons(PORT),
.sin_addr.s_addr = inet_addr(IP)
};
if(bind(oldfd,(struct sockaddr *)&send,sizeof(send)) == -1)
{
perror("bind");
return -1;
}
*/
//3、数据发送
struct sockaddr_in group = {
.sin_family = AF_INET,
.sin_port = htons(8888), //组播端口号
.sin_addr.s_addr = inet_addr("224.1.2.3") //组播IP地址
};
char buff[1024];
while(1)
{
fgets(buff,sizeof(buff),stdin);
buff[strlen(buff)-1] = '\0';
sendto(oldfd,buff,sizeof(buff),0,(struct sockaddr *)&group,sizeof(group));
if(strcmp(buff,"quit") == 0)
{
printf("发送端退出\n");
break;
}
}
close(oldfd);
return 0;
}
2.2组播接收端模型:
是要加入组播组才能收到信息
#include<myhead.h>
#define ZIP "224.1.2.3"
#define IP "191.168.191.129"
#define PORT 8888
int main(int argc, const char *argv[])
{
//1、创建基于UDP的套接字
int oldfd = socket(AF_INET,SOCK_DGRAM,0);
if(oldfd == -1)
{
perror("socket");
return -1;
}
//2、设置允许加入组播组
struct ip_mreqn allow = {
.imr_multiaddr.s_addr = inet_addr(ZIP),//组播组IP地址
.imr_address.s_addr = inet_addr(IP), //本机IP地址,标示该本机允许加入
.imr_ifindex = 3 //网卡索引ens35
};
if(setsockopt(oldfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&allow,sizeof(allow)) == -1)
{
perror("setsockopt");
return -1;
}
//绑定
//真正让本机加入组播里
struct sockaddr_in send = {
.sin_family = AF_INET,
.sin_port = htons(PORT), //组播端口号
.sin_addr.s_addr = inet_addr(ZIP) //组播IP地址
};
if(bind(oldfd,(struct sockaddr *)&send,sizeof(send)) == -1)
{
perror("bind");
return -1;
}
//4、信息收
char buff[1024];
while(1)
{
recvfrom(oldfd,buff,sizeof(buff),0,NULL,NULL);
printf("%s\n",buff);
}
return 0;
}
三、流式域套接字(TCP)
3.1流式域套接字服务器:
//流式域套接字服务器端实现
#include<myhead.h>
int main(int argc, const char *argv[])
{
//1、创建套接字
int oldfd = socket(AF_UNIX,SOCK_STREAM,0);
if(oldfd == -1)
{
perror("socket");
return -1;
}
//2、判断套接字文件存在就删除,并不会创建新的文件
if(access("./server",F_OK) == 0) //套接字文件server
{
if(unlink("./server") == -1)
{
perror("unlink");
return -1;
}
}//此段操作使得当前路径下的server文件已经被删掉了,没有了
//3、填充sockaddr_un结构体信息,绑定本地套接字文件
struct sockaddr_un server;
server.sun_family = AF_UNIX;
strcpy(server.sun_path,"server");//这里的server 只是一个字符串相当于 给即将创建的文件起个名字
if(bind(oldfd,(struct sockaddr *)&server,sizeof(server)) == -1)
{
perror("bind");
return -1;
}//bind 函数 使得原本已经不存在的server文件被重新创建
//4、监听
if(listen(oldfd,10) == -1)
{
perror("listen");
return -1;
}
//5、接受客户端请求
struct sockaddr_un client;
int client_len = sizeof(client);
int newfd = accept(oldfd,(struct sockaddr *)&client,&client_len);
if(newfd == -1)
{
perror("accept");
return -1;
}
printf("%s发来连接请求\n",client.sun_path); //输出客户端文件
char buff[1024];
while(1)
{
recv(newfd,buff,sizeof(buff),0);
strcat(buff,"追加加加加加加加到厌倦");
send(newfd,buff,sizeof(buff),0);
}
return 0;
}
3.2流式域套接字客户端:
//流式域套接字客户端实现
#include<myhead.h>
int main(int argc, const char *argv[])
{
//1、创建套接字
int oldfd = socket(AF_UNIX,SOCK_STREAM,0);
if(oldfd == -1)
{
perror("socket");
return -1;
}
//2、判断套接字文件存在就删除,并不会创建新的文件
if(access("./client",F_OK) == 0) //套接字文件server
{
if(unlink("./client") == -1)
{
perror("unlink");
return -1;
}
}//此段操作使得当前路径下的client文件已经被删掉了,没有了
//3、填充sockaddr_un结构体信息,绑定本地套接字文件
struct sockaddr_un client;
client.sun_family = AF_UNIX;
strcpy(client.sun_path,"./client");//这里的server 只是一个字符串相当于 给即将创建的文件起个名字
if(bind(oldfd,(struct sockaddr *)&client,sizeof(client)) == -1)
{
perror("bind");
return -1;
}//bind 函数 使得原本已经不存在的server文件被重新创建
//填充服务器结构体信息以便于发送给服务器
struct sockaddr_un server;
server.sun_family = AF_UNIX;
strcpy(server.sun_path,"server");
if(connect(oldfd,(struct sockaddr *)&server,sizeof(server)) == -1)
{
perror("connect");
return -1;
}
char buff[1024];
while(1)
{
fgets(buff,sizeof(buff),stdin);
send(oldfd,buff,sizeof(buff),0);
printf("发送成功\n");
bzero(buff,sizeof(buff));
recv(oldfd,buff,sizeof(buff),0);
printf("收到服务器信息%s\n",buff);
}
return 0;
}