I have recently learned epoll usage and have never understood it too well.
As mentioned on the internet, "ET (edge-triggered) only supports no-block socket. In this mode, when the descriptor is never ready, the kernel tells you through epoll. Then it will assume that you know that the file descriptor is ready and will not send more ready notifications for that file descriptor, until you do some operations, the file descriptor is no longer in the ready state ".
I wrote the code and tested it:
If the client sends 100 bytes, the server only reads 10 bytes each time. If epoll_wait sets a timeout and the client does not send data again, an in event is triggered when the timeout is reached, if you set the never-Timeout (epoll_wait (epfd, events, 20,-1) and the client no longer sends data, the in event will not be generated. If the client continues to send data, an in event will be generated or the server re-mod
An in event will arrive, so that you can read data that has not been read.
Set out after the in event, but no in is set in. If the client sends data, the out event is triggered.
If (events [I]. Events & epollin)
{
Ev. Data. FD = sockfd;
Ev. Events = epollout | epollet;
Epoll_ctl (epfd, epoll_ctl_mod, sockfd, & eV );
} Else if (events [I]. Events & epollout)
{
Cout <"epollout" <Endl;
// EV. Data. FD = sockfd;
// Set the read operation event for the test.
// EV. Events = epollin | epollet;
// Modify the event to be handled on sockfd to epolin
// Epoll_ctl (epfd, epoll_ctl_mod, sockfd, & eV );
}
If the client sends data multiple times, the server reads data until the error occurs after the in event is triggered for the first time by a single thread. Even if the client sends data multiple times, the in event is not triggered once the server receives the incoming event.
The single-threaded code is as follows:
If (events [I]. Events & epollin)
{
Printf ("epollin \ n );
Sockfd = events [I]. Data. FD;
Char Buf;
Sleep (3 );
While (read (sockfd, & Buf, 1)> 0)
{
Printf ("% C \ n", Buf );
}
}
If the client program closes the socket or closes unexpectedly, the in event is triggered and the Recv returns 0.
If you need to shut down, unplug the network cable, or power off, set keep-alive and do not set keep-alive for test.
When the socket is blocked:
(1) In the case of no keep-alive, the in event will not be received when the power is down and the network is pulled out; shutdown and program exit will trigger the in event, and the read will return 0;
(2) setting keep-alive on the client does not affect the server and will not generate an in event.
(3) set keep-alive on the server. If the network cable is unplugged, an in event is generated around tcp_keepintvl * tcp_keepcnt. If no data exists, Recv returns-1, the error message is connect Time Out (etimedout). If the kernel receives data in the queue, only one in event is triggered. The Recv returns the number of bytes read. If you continue to read the data, you will get connect.
Time out.
Non-blocking Socket:
(1) do not unplug the network cable and read it cyclically after the in event is accepted. If no data is readable, eagain resource temporarily unavailable (may be the same value as ewouldblock) is returned)
(2) socket blocking in other cases
The code for setting keep-alive is as follows:
Int socket_set_keepalive (int fd)
{
Int ret, error, flag, alive, idle, CNT, intv;
/* Set: Use keepalive on FD */
Alive = 1;
If (setsockopt (FD, sol_socket, so_keepalive, & alive, sizeof alive )! = 0)
{
Printf ("set keepalive error: % S. \ n", strerror (errno ));
Return-1;
}
/* No data in 10 seconds, trigger the retention mechanism, and send the retention package */
Idle = 10;
If (setsockopt (FD, sol_tcp, tcp_keepidle, & idle, sizeof idle )! = 0)
{
Printf ("set keepalive idle error: % S. \ n", strerror (errno ));
Return-1;
}
/* If no response is received, resend the live package in 5 seconds */
Intv = 5;
If (setsockopt (FD, sol_tcp, tcp_keepintvl, & intv, sizeof intv )! = 0)
{
Printf ("set keepalive intv error: % S. \ n", strerror (errno ));
Return-1;
}
/* If a live packet is not received three times in a row, the connection is considered invalid */
CNT = 3;
If (setsockopt (FD, sol_tcp, tcp_keepcnt, & CNT, sizeof CNT )! = 0)
{
Printf ("set keepalive CNT error: % S. \ n", strerror (errno ));
Return-1;
}
Return 0;
}
Keep-alive reference: http://blog.csdn.net/guomsh/article/details/8484222