socket实现简易聊天小程序

xiaoxiao2021-02-28  24

这是网络编程的小练习,在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; }
转载请注明原文地址: https://www.6miu.com/read-1250340.html

最新回复(0)