一、广播
发送方
#include <my_h.h>
#define GRE_IP "192.168.125.205"
#define GRE_PORT 6969
int main(int argc, const char *argv[])
{
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd<0)
{
perror("socket");
return -1;
}
printf("创建套接字成功\n");
int a=1;
if(setsockopt(sfd,SOL_SOCKET,SO_BROADCAST,&a,sizeof(a))<0)
{
perror("setsockopt");
return -1;
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(GRE_PORT); //接收方绑定的端口号
sin.sin_addr.s_addr = inet_addr(GRE_IP); //接收方绑定的IP
char s[100];
ssize_t res = 0;
while(1)
{
bzero(s, sizeof(buf));
printf("请输入>>> ");
fgets(s, sizeof(s), stdin);
s[strlen(s)-1] = 0;
if(sendto(sfd, s, sizeof(s), 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
perror("sendto");
return -1;
}
printf("发送成功\n");
}
close(sfd);
return 0;
}
接收方
#include <my.h_h>
#define PORT 8888
#define IP "192.168.125.205"
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd < 0)
{
perror("socket");
return -1;
}
printf("创建成功%d\n", sfd);
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET;
sin.sin_port = htons(PORT); //端口号的网络字节序,1024~49151
sin.sin_addr.s_addr = inet_addr(IP); //广播IP
//绑定接收方自身的地址信息
if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
perror("bind");
return -1;
}
printf("bind success\n");
struct sockaddr_in cin; //存储发送放的地址信息
socklen_t addrlen =sizeof(cin);
char s[100];
ssize_t res = 0;
while(1)
{
bzero(s, sizeof(s));
//接收数据 --->同时存储这个数据包是从哪里来的,即发送的地址
res = recvfrom(sfd, s, sizeof(s), 0, (struct sockaddr*)&cin, &addrlen);
if(res < 0)
{
perror("recvfrom");
return -1;
}
printf("[%s:%d] : %s\n", \
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), s);
}
//关闭套接字
close(sfd);
return 0;
}
二、组播
发送方
#include <my.h_h>
#define SER_PORT 8888 //接收方绑定的端口号
#define SER_IP "224.1.2.3" //组播IP : 224.0.0.0-239.255.255.255
int main(int argc, const char *argv[])
{
//创建报式套接字
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd < 0)
{
perror("socket");
return -1;
}
printf("socket create success cfd=%d\n", cfd);
//绑定客户端自身的地址信息---》非必须绑定
//若不绑定则操作系统会给客户端绑定本机IP及随机端口
//填充地址信息结构体给sendto函数使用,想发给谁就填谁的地址信息
//真实的地址信息结构体根据地址族指定 AF_INET: man 7 IP
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET;
sin.sin_port = htons(SER_PORT); //组播端口
sin.sin_addr.s_addr = inet_addr(SER_IP); //组播IP
char s[100];
ssize_t res = 0;
while(1)
{
bzero(s, sizeof(s));
printf("请输入>>> ");
fgets(s, sizeof(s), stdin);
s[strlen(s)-1] = 0;
//发送数据, 主动发送给指定接收放,例如这里可以主动发给接收方
if(sendto(cfd, s, sizeof(s), 0, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
perror("sendto");
return -1;
}
printf("sendto success\n");
}
//关闭套接字
close(cfd);
return 0;
}
接收方
#include <my.h_h>
#define PORT 8888 //端口号的网络字节序,1024~49151
#define GRP_IP "224.1.2.3" //组播IP 224.0.0.0-239.255.255.255
#define LOL_IP "192.168.125.205" //ifconfig 的本机IP
int main(int argc, const char *argv[])
{
//创建报式套接字
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sfd < 0)
{
perror("socket");
return -1;
}
printf("socket create success sfd=%d\n", sfd);
//加入多播组
struct ip_mreqn mq;
mq.imr_multiaddr.s_addr = inet_addr(GRP_IP); //组播IP
mq.imr_address.s_addr = inet_addr(LOL_IP); //本机IP,ifconfig
mq.imr_ifindex = 2; //网络设备索引号
if(setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mq, sizeof(mq)) < 0)
{
perror("setsockopt");
return -1;
}
printf("加入多播组 [%s] 成功\n", GRP_IP);
//填充地址信息结构体给bind函数使用
//真实的地址信息结构体根据地址族指定 AF_INET: man 7 IP
struct sockaddr_in sin;
sin.sin_family = AF_INET; //必须填AF_INET;
sin.sin_port = htons(PORT); //端口号的网络字节序,1024~49151
sin.sin_addr.s_addr = inet_addr(GRP_IP); //组播IP
//绑定接收方自身的地址信息
if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
perror("bind");
return -1;
}
printf("bind success\n");
struct sockaddr_in cin; //存储发送放的地址信息
socklen_t addrlen =sizeof(cin);
char s[100];
ssize_t res = 0;
while(1)
{
bzero(s, sizeof(s));
//接收数据 --->同时存储这个数据包是从哪里来的,即发送的地址
res = recvfrom(sfd, s, sizeof(s), 0, (struct sockaddr*)&cin, &addrlen);
if(res < 0)
{
perror("recvfrom");
return -1;
}
printf("[%s:%d] : %s\n", \
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), s);
}
//关闭套接字
close(sfd);
return 0;
}
三、TCP
#include <my_h.h>
int s_pid(int newfd,struct sockaddr_in cin);
#define PORT 6888
#define IP "192.168.154.54"
void header(int sig)
{
while(waitpid(-1,NULL,WNOHANG)<0);
return ;
}
int main(int argc, const char *argv[])
{
//回收僵尸进程信号
if(signal(SIGCHLD,header)==SIG_ERR)
{
perror("signal");
return -1;
}
//创建流式套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<-1)
{
perror("socket");
return -1;
}
printf("套接字创建成功\n");
//允许端口快速复用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("setsockopt");
return -1;
}
printf("允许端口快速复用成功\n");
//创建结构体由bind使用
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
sin.sin_addr.s_addr=inet_addr(IP);
//绑定地址信息
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)))
{
perror("bind");
return -1;
}
printf("绑定成功\n");
//将上面创建的套接字转换成被动监听状态
if(listen(sfd,128)<0)
{
perror("listen");
return -1;
}
printf("转换状态成功\n");
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
//连接客户端
while(1)
{
int newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd<0)
{
perror("accept");
return -1;
}
printf("客户端连接成功\n");
pid_t cpid=fork();
if(0==cpid)
{
s_pid(newfd,cin);
exit(0);
}
else if(cpid<0)
{
perror("fork");
return -1;
}
close(newfd);
}
close(sfd);
return 0;
}
int s_pid(int newfd,struct sockaddr_in cin)
{
char s[100];
ssize_t res;
while(1)
{
//清空数组
bzero(s,sizeof(s));
//接收数据
res=recv(newfd,s,sizeof(s),0);
if(res<0)
{
perror("recv");
return -1;
}
else if(res==0)
{
printf("客户端已下线\n");
break;
}
printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),s);
if(strcmp(s,"quit")==0)
break;
strcat(s,"wow");
if(send(newfd,s,sizeof(s),0)<0)
{
perror("send");
return -1;
}
printf("发送成功\n");
}
close(newfd);
return 0;
}
四、UDP
#include <my_h.h>
#include <pthread.h>
#define PORT 6888
#define IP "192.168.125.205"
void *s_tid(void *arg);
struct s_l
{
int newfd;
struct sockaddr_in cin;
};
int main(int argc, const char *argv[])
{
//创建流式套接字
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd<0)
{
perror("socket");
return -1;
}
printf("套接字创建成功\n");
//允许端口快速复用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
{
perror("setsockopt");
return -1;
}
printf("允许端口快速复用成功\n");
//创建结构体由bind使用
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
sin.sin_addr.s_addr=inet_addr(IP);
//绑定地址信息
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
perror("bind");
return -1;
}
printf("绑定成功\n");
//将上面创建的套接字转换成被动监听状态
if(listen(sfd,128)<0)
{
perror("listen");
return -1;
}
printf("转换状态成功\n");
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
//连接客户端
pthread_t tid;
struct s_l msg;
while(1)
{
int newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd<0)
{
perror("accept");
return -1;
}
printf("客户端连接成功\n");
msg.newfd=newfd;
msg.cin=cin;
if(pthread_create(&tid,NULL,s_tid,(void *)&msg)!=0)
{
fprintf(stderr,"创建失败__%d__\n",__LINE__);
return -1;
}
pthread_detach(tid);
}
close(sfd);
return 0;
}
void *s_tid(void *arg)
{
char s[100];
ssize_t res;
int newfd=((struct s_l *)arg)->newfd;
struct sockaddr_in cin=((struct s_l *)arg)->cin;
while(1)
{
//清空数组
bzero(s,sizeof(s));
//接收数据
res=recv(newfd,s,sizeof(s),0);
if(res<0)
{
perror("recv");
break;
}
else if(res==0)
{
printf("客户端已下线\n");
break;
}
printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),s);
if(strcmp(s,"quit")==0)
break;
strcat(s,"wow");
if(send(newfd,s,sizeof(s),0)<0)
{
perror("send");
break;
}
printf("发送成功\n");
}
close(newfd);
pthread_exit(NULL);
}