Preface
This section describes how to use basic Linux functions and epoll to compile a complete server and client example. The functions of the client and server are as follows:
The client reads a row from the standard input and sends it to the server.
The server reads a row from the network and then outputs the row to the client.
The client receives a response from the server and outputs this line to the standard output.
Server
CodeAs follows:
# Include <unistd. h>
# Include <sys/types. h> /* Basic System Data Types */
# Include <sys/socket. h> /* Basic socket Definitions */
# Include <netinet/ In . H> /* Sockaddr_in {} and other Internet defns */
# Include <ARPA/inet. h> /* INet (3) Functions */
# Include <sys/epoll. h> /* Epoll Function */
# Include <fcntl. h> /* Nonblocking */
# Include <sys/resource. h> /* Setrlimit */
# Include <stdlib. h>
# Include <errno. h>
# Include <stdio. h>
# Include < String . H>
# Define Maxepollsize 10000
# Define Maxline 10240
Int Handle (Int Connfd );
Int Setnonblocking ( Int Sockfd)
{
If (Fcntl (sockfd, f_setfl, fcntl (sockfd, f_getfd, 0 ) | O_nonblock) =- 1 ){
Return - 1 ;
}
Return 0 ;
}
Int Main ( Int Argc, Char ** Argv)
{
Int Servport = 6888 ;
Int Listenq = 1024 ;
Int Listenfd, connfd, kdpfd, NFDs, N, nread, curfds, acceptcount = 0 ;
Struct Sockaddr_in servaddr, cliaddr;
Socklen_t socklen = Sizeof ( Struct Sockaddr_in );
Struct Epoll_event EV;
Struct Epoll_event events [maxepollsize];
Struct Rlimit RT;
Char Buf [maxline];
/* Sets the maximum number of files that a process can open. */
Rt. rlim_max = Rt. rlim_cur = maxepollsize;
If (Setrlimit (rlimit_nofile, & RT) =- 1 )
{
Perror ( " Setrlimit Error " );
Return - 1 ;
}
Bzero (& servaddr, Sizeof (Servaddr ));
Servaddr. sin_family = af_inet;
Servaddr. sin_addr.s_addr = htonl (inaddr_any );
Servaddr. sin_port = htons (servport );
Listenfd = socket (af_inet, sock_stream, 0 );
If (Listenfd =- 1 ){
Perror ( " Can't create socket File " );
Return - 1 ;
}
Int Opt = 1 ;
Setsockopt (listenfd, sol_socket, so_reuseaddr, & OPT, Sizeof (OPT ));
If (Setnonblocking (listenfd) < 0 ){
Perror ( " Setnonblock Error " );
}
If (BIND (listenfd ,( Struct Sockaddr *) & servaddr, Sizeof ( Struct Sockaddr) =- 1 )
{
Perror ( " BIND error " );
Return - 1 ;
}
If (Listen (listenfd, listenq) =- 1 )
{
Perror ( " Listen Error " );
Return - 1 ;
}
/* Create an epoll handle and add the listening socket to the epoll collection. */
Kdpfd = epoll_create (maxepollsize );
Ev. Events = epollin | epollet;
Ev. Data. FD = listenfd;
If (Epoll_ctl (kdpfd, epoll_ctl_add, listenfd, & eV) < 0 )
{
Fprintf (stderr," Epoll set insertion error: FD = % d \ n " , Listenfd );
Return - 1 ;
}
Curfds = 1 ;
Printf ( " Epollserver startup, port % d, Max connection is % d, backlog is % d \ n " , Servport, maxepollsize, listenq );
For (;;){
/* Wait for an event to happen */
NFDs = epoll_wait (kdpfd, events, curfds ,- 1 );
If (NFDs =- 1 )
{
Perror ( " Epoll_wait " );
Continue ;
}
/* Process all events */
For (N = 0 ; N <NFDs; ++ N)
{
If (Events [N]. Data. FD = listenfd)
{
Connfd = accept (listenfd ,( Struct Sockaddr *) & cliaddr, & socklen );
If (Connfd < 0 )
{
Perror (" Accept Error " );
Continue ;
}
Sprintf (BUF, " Accept form % s: % d \ n " , Inet_ntoa (cliaddr. sin_addr), cliaddr. sin_port );
Printf ( " % D: % s " , ++ Acceptcount, Buf );
If (Curfds> = maxepollsize ){
Fprintf (stderr, " Too connected connection, more than % d \ n " , Maxepollsize );
Close (connfd );
Continue ;
}
If (Setnonblocking (connfd) < 0 ){
Perror ( " Setnonblocking Error " );
}
Ev. Events = epollin | epollet;
Ev. Data. FD = connfd;
If (Epoll_ctl (kdpfd, epoll_ctl_add, connfd, & eV) < 0 )
{
Fprintf (stderr, " Add socket '% d' to epoll failed: % s \ n " , Connfd, strerror (errno ));
Return - 1 ;
}
Curfds ++;
Continue ;
}
// Process client requests
If (Handle (events [N]. Data. FD) < 0 ){
Epoll_ctl (kdpfd, epoll_ctl_del, events [N]. Data. FD, & eV );
Curfds --;
}
}
}
Close (listenfd );
Return 0 ;
}
Int Handle ( Int Connfd ){
Int Nread;
Char Buf [maxline];
Nread = read (connfd, Buf, maxline ); // Read client socket stream
If (Nread = 0 ){
Printf ( " Client close the connection \ n " );
Close (connfd );
Return - 1 ;
}
If (Nread < 0 ){
Perror ( " Read Error " );
Close (connfd );
Return -1 ;
}
Write (connfd, Buf, nread ); // Response Client
Return 0 ;
}
Download and compile
Compile and start the server
GCC epollserver. C-o epollserver
./Epollserver
For the client, refer to the echoclient example of the Linux/Unix server and client socket programming getting started instance in this article to download and compile.