您的位置:首页 > 运维架构 > Linux

epoll实现linux进程通信

2013-07-26 16:52 204 查看
server.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <signal.h>
#include <sys/epoll.h>
#include <errno.h>

#define UNIX_DOMAIN "/tmp/UNIX.domain"

void handler(){

printf("clean program start\n");
//unlink(UNIX_DOMAIN);
remove(UNIX_DOMAIN);
printf("clean end.\n");
}

int main(void)
{
int lsn_fd, apt_fd;
struct sockaddr_un srv_addr;
struct sockaddr_un clt_addr;
socklen_t clt_len;
int ret;
int i;
char recv_buf[1024];
char send_buf[1024];

signal(SIGTERM,handler);

//create epoll
int epfd,eventfd;
struct epoll_event   ev,events[1024];

epfd = epoll_create(1024);

//create socket to bind local IP and PORT
lsn_fd = socket(AF_UNIX, SOCK_STREAM, 0);
ev.data.fd = lsn_fd;
ev.events = EPOLLIN|EPOLLET;

epoll_ctl(epfd,EPOLL_CTL_ADD,lsn_fd,&ev);

if(lsn_fd < 0)
{
perror("can't create communication socket!");
return 1;
}

//create local IP and PORT
srv_addr.sun_family = AF_UNIX;
strncpy(srv_addr.sun_path, UNIX_DOMAIN, sizeof(srv_addr.sun_path) - 1);
//unlink(UNIX_DOMAIN);

//bind sockfd and sockaddr
ret = bind(lsn_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));
if(ret == -1)
{
perror("can't bind local sockaddr!");
close(lsn_fd);
unlink(UNIX_DOMAIN);
return 1;
}

//listen lsn_fd, try listen 5

ret = listen(lsn_fd, 5);
if(ret == -1)
{
perror("can't listen client connect request");
close(lsn_fd);
unlink(UNIX_DOMAIN);

return 1;
}

clt_len = sizeof(clt_addr);
while(1)
{
int nfds = epoll_wait(epfd,events,1024,100);
int i=0;
for(i=0;i<nfds;++i)
{
if(events[i].data.fd == lsn_fd)
{
apt_fd = accept(lsn_fd, (struct sockaddr*)&clt_addr, &clt_len);
if(apt_fd < 0){
perror("can't listen client connect request");
close(lsn_fd);
unlink(UNIX_DOMAIN);
return 1;
}
char lines[256];
sprintf(lines,"server data  to client\n");
write(apt_fd, lines, 256);

ev.data.fd = apt_fd;
ev.events = EPOLLIN|EPOLLET;

epoll_ctl(epfd,EPOLL_CTL_ADD,apt_fd,&ev);

}
else if (events[i].events & EPOLLIN)
//write数据
{
printf("EPOLLIN\n");
if( (eventfd = events[i].data.fd) < 0 )
continue;

int n=0,ret=0 ;
char line[256];
if ((ret = read(eventfd,line,256)) < 0){

if(errno == ECONNRESET){
close(eventfd);
events[i].data.fd = -1;
}
else
printf("readline error\n");
}
else if( ret == 0){
close(eventfd);
events[i].data.fd = -1;
}
else if( ret > 0 )
{
line[ret] = '\0';
printf("%s",line);
while( ( ret = read(eventfd,line,256)) >0)
{
line[ret] = '\0';
printf("%s",line);
}
printf("\n");
}
}
else if (events[i].events & EPOLLOUT){
//写出的数据,在EPOLLIN处理中设置fd的events为EPOLLOUT|EPOLLET时,即触发该事件
int eventfd  = events[i].data.fd;
char line[256];
write(eventfd,line,256);

ev.data.fd = eventfd;
ev.events = EPOLLIN | EPOLLET;

epoll_ctl ( epfd, EPOLL_CTL_ADD, eventfd, &ev);
}
}
}

close(apt_fd);
close(lsn_fd);
unlink(UNIX_DOMAIN);
return 0;
}


client.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>

#define UNIX_DOMAIN "/tmp/UNIX.domain"

int main(void)
{
int connect_fd;
struct sockaddr_un srv_addr;
char snd_buf[256];
char rcv_buf[256];
int ret;
int i;
connect_fd = socket(AF_UNIX, SOCK_STREAM, 0);

if(connect_fd < 0)
{
perror("client create socket failed");
return 1;
}
srv_addr.sun_family = AF_UNIX;
strcpy(srv_addr.sun_path, UNIX_DOMAIN);
ret = connect(connect_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr));

if(ret == -1)
{
perror("connect to server failed!");
close(connect_fd);
unlink(UNIX_DOMAIN);
return 1;
}

memset(rcv_buf, 0, 256);
int rcv_num = read(connect_fd, rcv_buf, sizeof(rcv_buf));
printf("receive message from server (%d) :%s\n", rcv_num, rcv_buf);

memset(snd_buf, 0, 256);
strcpy(snd_buf, "message from client");
printf("sizeof(snd_buf): %d\n", sizeof(snd_buf));

printf("send data to server... ...\n");
for(i = 0; i < 4; i++)
{
write(connect_fd, snd_buf, sizeof(snd_buf));
}
printf("send end!\n");
close(connect_fd);
return 0;

}


与网络的socket通信的区别,即socket地址有些区别,其他的一样。

sockaddr_in用于网络的socket通信,sockaddr_un用于本机上的进程之间的通信。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: