SELECT
效果图
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/select.h>
//服务器
int main(int argc,const char** argv)
{
//创建socket
int ser_sock=socket(AF_INET,SOCK_STREAM,0);
if(0>ser_sock)
{
perror("socket");
return EXIT_FAILURE;
}
//准备通信
struct sockaddr_in ser_addr,cli_addr;
ser_addr.sin_family=AF_INET;
ser_addr.sin_port=htons(5678);
ser_addr.sin_addr.s_addr=INADDR_ANY;
socklen_t addrlen=sizeof(cli_addr);
//绑定
if(-1==bind(ser_sock,(struct sockaddr*)&ser_addr,addrlen))
{
perror("bind");
return EXIT_FAILURE;
}
//监听
if(-1==listen(ser_sock,5))
{
perror("listen");
return EXIT_FAILURE;
}
//准备select集
//创建集
fd_set reads;
//清空集
FD_ZERO(&reads);
//添加sock文件
FD_SET(ser_sock,&reads);
//设置超时时间
struct timeval timeout={3,50000};
//设置最大集
int fd_max=ser_sock;
//设置最小集
int fd_min=ser_sock;
char buf[4096]={};
printf("等待连接\n");
//循环接收
for(;;)
{
//创建一个备份集,准备给内核,因为内核使用完之后会把他破坏,内会会把有事件发生的文件描述
//符存储到集合中.
fd_set cpy_reads=reads;
//监听集合,select函数
int fd_num=select(fd_max+1,&cpy_reads,0,0,&timeout);
if(-1==fd_max)
{
perror("select");
return EXIT_FAILURE;
}
if(0==fd_num)continue;
//循环接受和发送
for(int fd=fd_min;fd<=fd_max;fd++)
{
//测试所有的文件描述符是否发生
if(FD_ISSET(fd,&cpy_reads))
{
//等待链接确认
if(fd==ser_sock)
{
//等待链接
int cli_sock=accept(ser_sock,(struct sockaddr*)&ser_addr,&addrlen);
if(-1==cli_sock)
{
perror("accept");
return EXIT_FAILURE;
}
//更新最小或是最大的集
if(cli_sock>fd_max)
{
fd_max=cli_sock;
}
if(cli_sock<fd_min)
{
fd_min=cli_sock;
}
//将sock添加到监听集
FD_SET(cli_sock,&reads);
printf("connect client:%d\n",cli_sock);
}
else
{
int ret_size=recv(fd,buf,sizeof(buf),0);
printf("recv:[ %s ],bits:%d\n",buf,ret_size);
if(0>=ret_size||0==strcmp("quit",buf))
{
perror("链接中断\n");
FD_CLR(fd,&reads);
close(fd);
continue;
}
printf("send\n");
strcat(buf,":return");
send(fd,buf,sizeof(buf),0);
printf("发送成功\n");
}
}
}
}
}
EXPOLL
效果图
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<sys/select.h>
#include<sys/epoll.h>
#define EPOLL_SIZE 100
//服务器端
int main(int argc,const char** argv)
{
//创建socket
int ser_sock=socket(AF_INET,SOCK_STREAM,0);
if(0>ser_sock)
{
perror("socket");
return EXIT_FAILURE;
}
//准备通信
struct sockaddr_in ser_addr,cli_addr;
ser_addr.sin_family=AF_INET;
ser_addr.sin_port=htons(5678);
ser_addr.sin_addr.s_addr=INADDR_ANY;
socklen_t addrlen=sizeof(cli_addr);
//绑定
if(-1==bind(ser_sock,(struct sockaddr*)&ser_addr,addrlen))
{
perror("bind");
return EXIT_FAILURE;
}
//监听
if(-1==listen(ser_sock,5))
{
perror("listen");
return EXIT_FAILURE;
}
char buf[4096]={};
//创建一个事件描述符
int epfd=epoll_create(EPOLL_SIZE);
if(0>epfd)
{
perror("epoll_create");
return EXIT_FAILURE;
}
struct epoll_event event={EPOLLIN};
struct epoll_event *events=malloc(sizeof(event)*EPOLL_SIZE);
event.data.fd=ser_sock;
epoll_ctl(epfd,EPOLL_CTL_ADD,ser_sock,&event);
//循环接收
for(;;)
{
//循环接受和发送
//监听,内核会把产生事件 的描述符存储到events,返回值表示
//事件描述符的数量
int cnt=epoll_wait(epfd,events,EPOLL_SIZE,-1);
printf("cnt:%d\n",cnt);
if(0>=cnt)
{
perror("epoll_wailt");
return EXIT_FAILURE;
}
//遍历所有产生事件的描述符
for(int i=0;i<cnt;i++)
{
//判断是否有新的客户端
if(events[i].data.fd==ser_sock)
{
//等待链接
int cli_sock=accept(ser_sock,(struct sockaddr*)&ser_addr,&addrlen);
if(-1==cli_sock)
{
perror("accept");
return EXIT_FAILURE;
}
//加入到epoll对象
event.data.fd=cli_sock;
event.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,cli_sock,&event);
printf("connect client:%d\n",cli_sock);
}
else
{
//有新的数据要读取
int ret_size=recv(events[i].data.fd,buf,sizeof(buf),0);
printf("recv:[ %s ],bits:%d\n",buf,ret_size);
if(0>=ret_size||0==strcmp("quit",buf))
{
perror("链接中断\n");
epoll_ctl(epfd,EPOLL_CTL_DEL,events[i].data.fd,NULL);
close(events[i].data.fd);
continue;
}
printf("send\n");
strcat(buf,":return");
send(events[i].data.fd,buf,sizeof(buf),0);
printf("发送成功\n");
}
}
}
}
客户端代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
//客户端
int main(int argc,const char** argv)
{
//创建socket
int clifd=socket(AF_INET,SOCK_STREAM,0);
//初始化地址簇
struct sockaddr_in addr={};
addr.sin_family=AF_INET;
//初始化端口
addr.sin_port=htons(5678);
//初始化地址
addr.sin_addr.s_addr=INADDR_ANY;
//初始化长度
socklen_t addrlen=sizeof(addr);
//链接
printf("连接中...\n");
sleep(2);
if(connect(clifd,(struct sockaddr*)&addr,addrlen))
{
perror("connect");
return EXIT_FAILURE;
}
printf("连接成功,正在准备通信.....\n");
sleep(3);
//发送/接受数据
char buf[4096]={};
size_t buf_size=sizeof(buf);
for(;;)
{
printf("\n>>>");
gets(buf);
send(clifd,buf,strlen(buf)+1,0);
if(0==strcmp("quit",buf))
{
printf("通信结束\n");
break;
}
printf("recv...");fflush(stdout);
size_t ret_size=recv(clifd,buf,buf_size,0);
if(0==ret_size)
{
printf("网络中断\n");
break;
}
if(0==strcmp("quit",buf))
{
printf("通信结束\n");
break;
}
printf("\nrecv:[ %s ],bits:%d\n",buf,strlen(buf)+1);
}
//关闭文件
close(clifd);
}