//server.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(){
//socket - IPv4 - TCP
int sockfd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == sockfd)
{
perror("socket");
return -1;
}
printf("创建成功sockfd = %d\n",sockfd);
//bind - struct - 三个参数-sockfd,(struct sockaddr *)&saddr,sizeof(saddr)
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8848);
saddr.sin_addr.s_addr = inet_addr("192.168.7.26");
if(-1 == bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr)))
{
perror("bind");
return -1;
}
printf("绑定成功\n");
//listen - 两个参数 - sockfd - int n
if(-1 == listen(sockfd,10))
{
perror("listen");
return -1;
}
printf("监听成功\n");
//poll - 定义结构体- 初始化为负数 - 添加文件描述符sokcfd
struct polled fds[32];
for (int i=0;i<32;i++)
{
fds[i].fd = -1;
}
int nfds = 0; //实际文件描述符个数
fds[nfds].fd = sockfd;
fds[nfds].events = POLLIN; //POLLIN读 POLLOUT写 读写相同表示产生IO事件
nfds ++;
while(1)
{
poll(fd,nfds,-1)
//int poll(struct pollfd *fds, nfds_t nfds, int timeout); timeout=-1表示阻塞等待事件
for (int i=0;i
头文件:#include
函数原型:int getsockopt (int sockfd, int level, int optname,void *optval, socklen_t *optlen);
int setsockopt (int sockfd, int level, int optname,const void *optval, socklen_t optlen);
sockfd:套接字
level:设置属性层
SOL_SOCKET:通用套接字层
IPPROTO_IP:IP层
IPPRO_TCP:TCP层
sockfd = socket(AF_INET,SOCK_STREAM,0);
int opt = 1;
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
//UDP IPv4 发送端(客户端)
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
int opt = 1;
setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt));
//绑定接收方端口和广播地址
//发送数据
//UDP IPv4 接收方(服务端)
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
//加入多播组
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("224.10.10.10");
mreq.imr_interface.s_addr = inet_addr("0.0.0.0");
setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
//sockfd - ip 绑定
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8848);
saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
//等待接收数据
char buf[32] = {0};
while(1){
recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL);
printf("buf:%s\n",buf);
memset(buf,0,sizeof(buf));
}
struct timeval timeout = {5,0} //grep -r -n "struct timeval {" /usr/include/ 可查结构体
//接收超时
setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout)); //注意第四个四五个参数
void hanlder(int arg){
printf("timeout!\n");
}
int main(){
signal(SIGALRM,handler);
alarm(5);
//程序运行开始后,开始循环打印hello,后台计时,5秒到了之后,发送SIGALRM信号(定时终止程序)
//加了handler参数后,将会执行handler函数来取代发送定时终止信号
//如果此处加pause() 刚开始将会一次都不打印hello,后台计时5s后直接执行hanlder函数
//等同于raise(SIGALRM)
//signal宏函数复习:SIG_DFL SIG_IGN
while(1){
printf("hello\n");
sleep(1);
}
return 0;
}
select poll epoll函数参数中将最后一个参数NULL改为&timeout(struct timeval类型)
//select
struct timeval timeout = {5,0}; //5s + 0us
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(sockfd,&rfds);
int maxfd = sockfd;
select(maxfd+1,&rfds,NULL,NULL,&timeout); //多配置一个超时等待时间
//
poll(fds,nfds,-1);//阻塞等待事件
//NULL -- 阻塞等待
网段:192.168.7 由ip地址和子网掩码255.255.255.0相与得来
xxx.xxx.xxx.255是广播地址
广播与UDP:UDP不关注对方是否收到
//send.c
#include
#include
#include
#include
#include
#include
#include
#include
int main(){
//socket
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if (sockfd<0){
perror("socket");
return -1;
}
//setsockopt
int opt = 1;
setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt));
//设置接收方端口信息
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8848);
saddr.sin_addr.s_addr = inet_addr("192.168.7.255"); //ip填广播地址
//read sendto
char buf[32] = {0};
while(1){
read(0,buf,sizeof(buf));
sendto(sockfd,buf,sizeof(buf),(struct sockaddr *)&saddr,sizeof(saddr));
memset(buf,0,sizeof(buf));
}
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
int main(){
//socket 数据报套接字
int sockfd = socket(AF_INET, SOCK_DGRAM,0);
if (sockfd<0){
perror(""socket);
return -1;
}
//bind
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8848); //收听同一个广播,端口和地址都必须相同
saddr.sin_addr.s_addr = inet_addr("192.168.7.255"); //也可以填0.0.0.0
bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
//recvfrom
char recvBuf[32] = {0};
while(1)
{
recvfrom(sockfd,recvBuf,sizeof(recvBuf),0,NULL,NULL);
printf("recvBuf:%s\n",recvBuf);
memset(recvBuf,0,sizeof(recvBuf));
}
return 0;
}
//广播 -- 总结
发送方:
1.socket
2.setsockopt(sockfd,SO_SOCKET,SOBROADCAST,&opt,sizeof(opt));
3.指定发送方端口信息(端口+广播地址 结构体)
4.while(1){sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&sockaddr,sizeof(saddr))}
接收方(服务器):
1.socket
2.bind绑定接收方端口信息(端口+广播地址 结构体)
3.while(1){recvfrom(sockfd,buf,sizeof(buf),NULL,NULL}
UDP才能广播
发送方向广播地址发送数据,所有绑定了广播地址和同样端口的接收方都能收到
//send.c
#include
#include
#include
#include
#include
#include
#include
#include
int main(){
//socket
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
//指定接收方 -- 组播地址
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8848);
saddr.sin_addr.s_addr = inet_addr("224.10.10.10");
//sendto
char sendBuf[32] = {0};
while(1)
{
read(0,sendBuf,sizeof(sendBuf));
sendto(sockfd,sendBuf,sizeof(sendBuf),0,(struct sockaddr *)&saddr,sizeof(saddr));
}
return 0;
}
//recv.c
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
//socket
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
//加入多播组
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("224.10.10.10");
mreq.imr_interface.s_addr = inet_addr("0.0.0.0");
setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));
//bind
struct sockaddr_in saddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8848);
saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
//recvfrom
char recvBuf[32] = {0};
while(1)
{
recvfrom(sockfd,recvBuf,sizeof(recvBuf),0,NULL,NULL);
printf("recvBuf:%s\n",recvBuf);
memset(recvBuf,0,sizeof(recvBuf));
}
return 0;
}
AF_UNIX 而非IPv4的AF_INET
//AF_INET;--->ipv4 --->struct sockaddr_in
//AF_UNIX;--->struct sockaddr_un
//struct sockaddr_un saddr ={AF_UNIX,"socket"};
//UDP -- AF_UNIX
//server.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
//socket
int sockfd = socket(AF_UNIX, SOCK_DGRAM, 0);
//bind
struct sockaddr_un saddr;
saddr.sun_family = AF_UNIX;
strcpy(saddr.sun_path,"socket");
bind(sockfd,(struct sockaddr *)&saddr, sizeof(saddr));//转为通用结构体
//recvfrom
char recvBuf[32] = {0};
while(1){
recvfrom(sockfd,recvBuf,sizeof(recvBuf),0,NULL,NULL);
printf("recvBuf:%s\n",recvBuf);
bzero(recvBuf,sizeof(recvBuf)) //memset
}
return 0;
}
//client.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
//socket
int sockfd = socket(AF_UNIX,SOCK_DGRAM,0);
//struct
struct sockaddr_un saddr = {AF_UNIX,"socket"};
// saddr.sun_family = AF_UNIX;
// strcpy(saddr.sun_path,"socket");
//sendto
char sendBuf[32] = {0};
while(1){
read(0,sendBuf,sizeof(sendBuf));
sendto(sockfd,sendBuf,sizeof(sendBuf),0,(struct sockaddr *)&saddr,sizeof(saddr));
//别忘了中间有个flags -- 0
bzero(sendBuf,sizeof(sendBuf));
}
return 0;
}
poll:
流程:strct polled fds[32]-> for -1-> nfds=0->添加fds[nfds].fd=sockfd;fds[nfds].events=POLLIN->while(1){poll(fds,nfds,-1)}
//poll的三个参数:结构体首地址、元素个数、超时(-1表示阻塞等待事件)
select:
流程:fd_set rfds,tmp;FD_ZERO;FD_SET;maxfd; while(1){select(nfds=maxfd+1,&tmp,NULL,NULL,&timeout)}
//注意第一个参数是表的元素个数,而maxfd是最大的文件描述符
setsockopt()设置套接字属性参数
//参数:(sockfd,SOL_SOCKET,SO_BROADCAST,&timeout,sizeof(timeout)
alarm(5)
//表示程序运行开始后,后台计时5s然后发送程序终止信号(SIGALRM)
//signal(5,hanlder)函数中,表示执行hanlder取代原先的信号发送
广播-UDP-IPv4
send:socket-setsockopt-struct-sendto
recv:socket-struct-bind-recvfrom
组播-UDP-IPv4
send:socket-struct-sendto
recv:socket-setsockopt-struct-bind-recvfrom
Unix-UDP-AF_UNIX
server:socket-struct-bind-recvfrom
client:socket-struct-sendto