/*****************************************
*Discription:用socket实现远程登录访问 用epoll_wait实现并发 两个端口进行通信
*socket 产生用于监听的描述符 bind 绑定地址和端口 listen 把套接字设为被动 accept()用于产生和客户机进行交 互的文件描述符
*
*
*
*
* *********************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h> //inet_ntop()
#include <sys/epoll.h>
#define SERV_port 8000 //端口号
#define max_r 100 //存取从客户端读过来的空间
#define max_ep 10 //从内核可以处理事件集合的大小
char buf_f[1024];
int flag_fd[100];
int f_fd;
int main(void)
{
int listenfd, connfd;
char buf[100];
char buf1[100];
int r_len;
char str[INET_ADDRSTRLEN]; //。。。。。。。
struct sockaddr_in servaddr, cliaddr;
int ep_fd, cur_ep, accept_Count = 0; //ep_fd创建的句柄用于处理wait的epoll文件描述符 cur_ep用于记录当前epoll_wait监听事件的个数
int nfds, i, j; //epoll_wait返回的处理事件的个数
struct epoll_event ep_env; //用于注册事件
struct epoll_event events[max_ep];//用于回传要处理的事件
listenfd = socket(AF_INET, SOCK_STREAM, 0);
int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_port);
if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1){
perror("bind fail\n");
}
if(listen(listenfd, 20) == -1){
perror("listen fail\n");
}
printf("now we can accept connections\n");
//创建epoll句柄 并把监听socket加入epoll队列
if((ep_fd = epoll_create(1)) == -1){
perror("epoll_create fail\n");
exit(-1);
}
memset(flag_fd, 0, sizeof(flag_fd));
ep_env.data.fd = listenfd;
ep_env.events = EPOLLIN | EPOLLET;
if((epoll_ctl(ep_fd, EPOLL_CTL_ADD, listenfd, &ep_env)) == -1){
perror("epoll_ctl fail\n");
}
//把服务器标准输入加入epoll队列
ep_env.data.fd = STDIN_FILENO;
ep_env.events = EPOLLIN | EPOLLET;
if((epoll_ctl(ep_fd, EPOLL_CTL_ADD, STDIN_FILENO, &ep_env)) == -1){
perror("epoll_ctl fail\n");
}
flag_fd[listenfd] = 1;
flag_fd[STDIN_FILENO] = 1;
printf("epoll_server start server port:%d\n", SERV_port);
cur_ep = 2;
while(1){
nfds = epoll_wait(ep_fd, events, cur_ep, -1);
for(i = 0; i < nfds; i++){
if(events[i].data.fd == listenfd){
int cliaddr_len = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
sprintf(buf, "accept from %s at port %d\n",
inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port);
printf("%d:%s", ++accept_Count, buf);
ep_env.events = EPOLLIN | EPOLLET;
ep_env.data.fd = connfd;
epoll_ctl(ep_fd, EPOLL_CTL_ADD, connfd, &ep_env);
flag_fd[connfd] = 1;
cur_ep++;
continue;
}
else if(events[i].data.fd == STDIN_FILENO){
if(handle(events[i].data.fd, connfd) < 0) {
epoll_ctl(ep_fd, EPOLL_CTL_DEL, j, &ep_env);
close(events[i].data.fd);
cur_ep--;
flag_fd[events[i].data.fd] = 0;
}
}
else{
if(handle(events[i].data.fd, STDIN_FILENO) < 0){
epoll_ctl(ep_fd, EPOLL_CTL_DEL, connfd, &ep_env);
close(events[i].data.fd);
cur_ep--;
flag_fd[events[i].data.fd] = 0;
}
}
}
/*
int cliaddr_len = sizeof(cliaddr);
while((r_len = read(connfd, buf, max_r))){
printf("received from %s at port %d\n",
inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
ntohs(cliaddr.sin_port));
write(connfd, buf, r_len);
}*/
}
close(listenfd);
return 0;
}
//从src复制到dest
int handle(int src, int dest) {
int nread;
int j;
char buf[1024];
nread = read(src, buf, 1024);
if(nread == 0){
printf("client close the connection\n");
return -1;
}
if(nread < 0){
perror("read error");
return -1;
}
for(j = 0; j < 100; j++)
if(j != 3 && j != src && flag_fd[j] == 1)
write(j, buf, nread);
return 0;
}
epoll - socket-server-client
最新推荐文章于 2022-09-26 23:26:11 发布