static int start(int port,char *ip)
{
assert(ip);
int sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0)
{
perror("socket");
exit(1);
}
struct sockaddr_in local;
local.sin_port=htons(port);
local.sin_family=AF_INET;
local.sin_addr.s_addr=inet_addr(ip);
int opt=1; //设置为接口复用
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
{
perror("bind");
exit(2);
}
if(listen(sock,_BACKLOG_)<0)
{
perror("listen");
exit(3);
}
return sock;
}
static int epoll_server(int listen_sock)
{
int epoll_fd=epoll_create(256);//生成一个专用的epoll文件描述符
if(epoll_fd<0)
{
perror("epoll_create");
exit(1);
}
struct epoll_event ev;//用于注册事件
struct epoll_event ret_ev[_MAX_];//数组用于回传要处理的事件
int ret_num=_MAX_;
int read_num=-1;
ev.events=EPOLLIN;
ev.data.fd=listen_sock;
if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,listen_sock,&ev)<0)//用于控制某个文件描述符上的事件(注册,修改,删除)
{
perror("epoll_ctl");
return -2;
}
int done=0;
int i=0;
int timeout=5000;
struct sockaddr_in client;
socklen_t len=sizeof(client);
while(!done)
{
switch(read_num=epoll_wait(epoll_fd,ret_ev,ret_num,timeout))//用于轮寻I/O事件的发生
{
case0:
printf("time out\n");
break;
case -1:
perror("epoll");
exit(2);
default:
{
for(i=0;i<read_num;++i)
{
if(ret_ev[i].data.fd==listen_sock&&(ret_ev[i].events&EPOLLIN))
{
int fd=ret_ev[i].data.fd;
int new_sock=accept(fd,(struct sockaddr*)&client,&len);
if(new_sock<0)
{
perror("accept");
continue;
}
ev.events=EPOLLIN;
ev.data.fd=new_sock;
epoll_ctl(epoll_fd,EPOLL_CTL_ADD,new_sock,&ev);
printf("get a new client...\n");
}
else //normal sock
{
if(ret_ev[i].events&EPOLLIN)
{
int fd=ret_ev[i].data.fd;
data_buf_p mem=(data_buf_p)malloc(sizeof(data_buf_t));
if(!mem)
perror("malloc");
continue;
}
mem->fd=fd;
memset(mem->buf,'\0',sizeof(mem->buf));
ssize_t _s=read(mem->fd,mem->buf,sizeof(mem -> buf)-1);
if(_s>0)
{
mem->buf[_s-1]='\0';
printf("client: %s\n",mem->buf);
ev.events=EPOLLOUT;
ev.data.ptr=mem;
epoll_ctl(epoll_fd,EPOLL_CTL_MOD,fd,&ev);
}
else if(_s==0)
{
printf("client close...\n");
epoll_ctl(epoll_fd,EPOLL_CTL_DEL,fd,NULL);
close(fd);
free(mem);
}
else
{
continue;
}
}
else if(ret_ev[i].events&EPOLLOUT) //写事件准备就绪
{
data_buf_p mem=(data_buf_p)ret_ev[i].data.ptr;
int fd=mem->fd;
char *buf=mem->buf;
write(fd,buf,strlen(buf));
ev.events=EPOLLIN; //写完,下次关心读事件
ev.data.fd=fd;
epoll_ctl(epoll_fd,EPOLL_CTL_MOD,fd,&ev);
}
else{
//....
}
}
}
}
break;
}
}
}
本地socket实现进程间通信-代码
最新推荐文章于 2023-05-22 10:45:52 发布