这是网络编程的小练习,在Linux下用socket,epoll实现服务器端与客户端的通信。
代码如下:
服务器端:
#include"func.h"
//用进程池实现服务器端向客户端并行传输文件
int main()
{
int sfd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in seraddr,cliaddr;//cliaddr用于accept函数
int ret;
int len_client=sizeof(cliaddr);
seraddr.sin_family=AF_INET;
seraddr.sin_port=htons(2000);
seraddr.sin_addr.s_addr=inet_addr("192.168.13.128");
ret=bind(sfd,(struct sockaddr*)&seraddr,sizeof(seraddr));//绑定IP和端口号
if(ret==-1){
perror("bind");
return -1;
}
listen(sfd,10);//开始监听
//构造进程池
int epfd=epoll_create(1);
struct epoll_event event,evs[3];
memset(&event,0,sizeof(event));
event.data.fd=sfd;
event.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,sfd,&event);//注册sfd
memset(&event,0,sizeof(event));
event.data.fd=0;
event.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,0,&event);//注册标准输入
memset(&cliaddr,0,sizeof(cliaddr));
int readyNum,i,new_fd;
char buf[128];
while(1)
{
memset(evs,0,sizeof(evs));
readyNum=epoll_wait(epfd,evs,3,-1);
for(i=0;i<readyNum;i++)//遍历就绪态的文件描述符,并执行相应的任务
{
if(evs[i].data.fd==sfd)
{
new_fd=accept(sfd,(struct sockaddr*)&cliaddr,&len_client);
if(new_fd==-1){
perror("accept");
return -1;
}
event.data.fd=new_fd;
event.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,new_fd,&event);//注册new_fd
printf("connect successfully\n");
}
if(evs[i].data.fd==new_fd)//从对端读取
{
memset(buf,0,sizeof(buf));
ret=recv(new_fd,buf,sizeof(buf),0);
if(ret>0)
printf("%s\n",buf);
else if(ret==0){
printf("byebye\n");
close(new_fd);
event.data.fd=new_fd;
event.events=EPOLLIN;//
epoll_ctl(epfd,EPOLL_CTL_DEL,new_fd,&event);//移除new_fd
}
}
if(evs[i].data.fd==0)//向对端发送数据
{
memset(buf,0,sizeof(buf));
read(0,buf,sizeof(buf));
send(new_fd,buf,strlen(buf)-1,0);
}
}
}
close(new_fd);
close(sfd);
return 0;
}
客户端:
#include"func.h"
//客户端
int main()
{
int sfd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in seraddr;
int ret;
seraddr.sin_family=AF_INET;
seraddr.sin_port=htons(2000);
seraddr.sin_addr.s_addr=inet_addr("192.168.13.128");
ret=connect(sfd,(struct sockaddr*)&seraddr,sizeof(seraddr));//客户端请求连接
if(ret==-1){
perror("connect");
return -1;
}
//构造进程池
int epfd=epoll_create(1);
struct epoll_event event,evs[2];
memset(&event,0,sizeof(event));
event.data.fd=sfd;
event.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,sfd,&event);//注册sfd
memset(&event,0,sizeof(event));
event.data.fd=0;
event.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,0,&event);//注册标准输入
char buf[128];
int readyNum,i;
while(1)
{
memset(evs,0,sizeof(evs));//每次用epoll_wait前先清空evs
readyNum=epoll_wait(epfd,evs,2,-1);
for(i=0;i<readyNum;i++)
{
if(evs[i].data.fd==sfd)//从服务器端读数据
{
memset(buf,0,sizeof(buf));
ret=recv(sfd,buf,sizeof(buf),0);
if(ret>0)
printf("%s\n",buf);
else if(ret==0){
printf("byebye\n");
exit(0);
}
}
if(evs[i].data.fd==0)//向对端发送数据
{
memset(buf,0,sizeof(buf));
ret=read(0,buf,sizeof(buf));
ret=send(sfd,buf,strlen(buf)-1,0);
if(ret==-1){
perror("send");
return -1;
}
}
}
}
return 0;
}