epoll基于socket
先上socket服务端
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define MAXPENDING 5 /* Max connection requests */
#define BUFFSIZE 32
void Die(char *mess) { perror(mess); exit(1); }
void HandleClient(int sock) {
char buffer[BUFFSIZE];
int received = -1;
if ((received = recv(sock, buffer, BUFFSIZE, 0)) < 0) {
Die("Failed to receive initial bytes from client");
}
while (received > 0) {
if (send(sock, buffer, received, 0) != received) {
Die("Failed to send bytes to client");
}
if ((received = recv(sock, buffer, BUFFSIZE, 0)) < 0) {
Die("Failed to receive additional bytes from client");
}
}
close(sock);
}
int main(int argc, char *argv[]) {
int serversock, clientsock;
struct sockaddr_in echoserver, echoclient;
if (argc != 2) {
fprintf(stderr, "USAGE: echoserver <port>\n");
exit(1);
}
if ((serversock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
Die("Failed to create socket");
}
memset(&echoserver, 0, sizeof(echoserver)); /* Clear struct */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = htonl(INADDR_ANY); /* Incoming addr */
echoserver.sin_port = htons(atoi(argv[1])); /* server port */
if (bind(serversock, (struct sockaddr *) &echoserver,sizeof(echoserver)) < 0) { /* Bind the server socket */
Die("Failed to bind the server socket");
}
if (listen(serversock, MAXPENDING) < 0) { /* Listen on the server socket */
Die("Failed to listen on server socket");
}
while (1) {
unsigned int clientlen = sizeof(echoclient);
if ((clientsock =accept(serversock, (struct sockaddr *) &echoclient,&clientlen)) < 0) {/* Wait for client connection */
Die("Failed to accept client connection");
}
fprintf(stdout, "Client connected: %s\n",inet_ntoa(echoclient.sin_addr));
HandleClient(clientsock);
}
}
client
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define BUFFSIZE 32
void Die(char *mess) {perror(mess);exit(1);}
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in echoserver;
char buffer[BUFFSIZE];
unsigned int echolen;
int received = 0;
if (argc != 4) {
fprintf(stderr, "USAGE: TCPecho <server_ip> <word> <port>\n");
exit(1);
}
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
Die("Failed to create socket");
}
memset(&echoserver, 0, sizeof(echoserver)); /* Clear struct */
echoserver.sin_family = AF_INET; /* Internet/IP */
echoserver.sin_addr.s_addr = inet_addr(argv[1]); /* IP address */
echoserver.sin_port = htons(atoi(argv[3])); /* server port */
if (connect(sock,(struct sockaddr *) &echoserver,sizeof(echoserver)) < 0) {
Die("Failed to connect with server");
}
echolen = strlen(argv[2]);
if (send(sock, argv[2], echolen, 0) != echolen) {
Die("Mismatch in number of sent bytes");
}
fprintf(stdout, "Received: ");/* Receive the word back from the server */
while (received < echolen) {
int bytes = 0;
if ((bytes = recv(sock, buffer, BUFFSIZE-1, 0)) < 1) {
Die("Failed to receive bytes from server");
}
received += bytes;
buffer[bytes] = '\0'; /* Assure null terminated string */
fprintf(stdout, buffer);
}
fprintf(stdout, "\n");
close(sock);
exit(0);
}
epoll在这个基础上改造一下
epolltest.c
#include <iostream>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
using namespace std;
#define MAXLINE 5
#define OPEN_MAX 100
#define LISTENQ 20
#define SERV_PORT 5000
#define INFTIM 1000
void setnonblocking(int sock){
int opts;
opts=fcntl(sock,F_GETFL);//apue第三章讲了
if(opts<0){
perror("fcntl(sock,GETFL)");
exit(1);
}
opts = opts|O_NONBLOCK;
if(fcntl(sock,F_SETFL,opts)<0){
perror("fcntl(sock,SETFL,opts)");
exit(1);
}
}
int main(){
int i, maxi, listenfd, connfd, sockfd,epfd,nfds;
ssize_t n;
char line[MAXLINE];
socklen_t clilen;
struct epoll_event ev,events[20];//声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
epfd=epoll_create(256);//生成用于处理accept的epoll专用的文件描述符
struct sockaddr_in clientaddr,serveraddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
//setnonblocking(listenfd);//把socket设置为非阻塞方式
ev.data.fd=listenfd;//设置与要处理的事件相关的文件描述符
ev.events=EPOLLIN|EPOLLET;//ev.events=EPOLLIN;
epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);//注册epoll事件,EPOLL_CTL_ADD
bzero(&serveraddr, sizeof(serveraddr));//memset(&echoserver, 0, sizeof(echoserver));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);//char *local_addr="192.168.229.129";inet_aton(local_addr,&(serveraddr.sin_addr));
serveraddr.sin_port=htons(SERV_PORT);
bind(listenfd,(sockaddr *)&serveraddr, sizeof(serveraddr));
listen(listenfd, LISTENQ);
maxi = 0;
while(1){//for ( ; ; ) {
nfds=epoll_wait(epfd,events,20,500);//等待epoll事件的发生
for(i=0;i<nfds;++i){
if(events[i].data.fd==listenfd){
connfd = accept(listenfd,(sockaddr *)&clientaddr, &clilen);
if(connfd<0){
perror("connfd<0");
exit(1);
}
//setnonblocking(connfd);
char *str = inet_ntoa(clientaddr.sin_addr);
cout << "accapt a connection from " << str << endl;
ev.data.fd=connfd;//设置用于读操作的文件描述符
ev.events=EPOLLIN|EPOLLET; //ev.events=EPOLLIN;//设置用于注测的读操作事件
epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);//注册ev
}else if(events[i].events&EPOLLIN){
cout << "EPOLLIN" << endl;
if ( (sockfd = events[i].data.fd) < 0) continue;
if ((n = read(sockfd, line, MAXLINE)) < 0) {
if (errno == ECONNRESET) {
close(sockfd);
events[i].data.fd = -1;
} else{
std::cout<<"readline error"<<std::endl;
}
} else if (n == 0) {
close(sockfd);
events[i].data.fd = -1;
}
line[n] = '\0';
cout << "read " << line << endl;
ev.data.fd=sockfd;//描述符
ev.events=EPOLLOUT|EPOLLET;//设置用于注测的写操作事件 //修改sockfd上要处理的事件为EPOLLOUT //epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
}else if(events[i].events&EPOLLOUT){
sockfd = events[i].data.fd;
write(sockfd, line, n);
ev.data.fd=sockfd;//设置用于读操作的文件描述符
ev.events=EPOLLIN|EPOLLET;//设置用于注测的读操作事件
epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);//修改sockfd上要处理的事件为EPOLIN
}
}
}
return 0;
}