epoll实现TCP通信

常见指令:telent 127.0.0.1 8080 连接

     service iptables stop 关闭防火墙

在TCP连接中,主动关闭连接的一方会进入2MSL,如果是服务器端,当TIME_WAIT时,sock不能被复用(四次挥手),使用setsockopt解决。

int opt=1;

setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

epoll是linux内核为处理大批量文件描述符而作了改进的poll,是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。另一点原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件异步唤醒而加入Ready队列的描述符集合就行了。

注:epoll除了提供select/poll那种IO事件的水平触发(Level Triggered)外,还提供了边缘触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少epoll_wait/epoll_pwait的调用,提高应用程序效率。

注:epoll文件描述符用完后,直接用close关闭即可,非常方便。事实上,任何被侦听的文件符只要其被关闭,那么它也会自动从被侦听的文件描述符集合中删除,很是智能。

epoll相关的系统调用有:epoll_create, epoll_ctl和epoll_wait。

1.epoll_create用来创建一个epoll文件描述符。

wKiom1dH77OCjJVQAABU3kR1DuU876.png

返回值:

>0:非空文件描述符;

-1:函数调用失败,同时会自动设置全局变量errno;

2.epoll_ctl用来添加/修改/删除需要侦听的文件描述符及其事件.

epoll的事件注册函数,它不同于select()是在监听事件时告诉内核要监听什么类型的事件,而是在这里先注册要监听的事件类型。

wKiom1dH8MrywmAtAAAUreDSt0o786.png

epfd:epoll_create的返回值

op:表示动作,为以下三个宏任意一个(根据需要):添加,修改,删除

wKiom1dH77bhXTF0AABMs-P0fYs984.png

fd:为关心的描述符

event为:关心描述符事件

wKioL1dH8K2DhOvRAAAn1esxeEw388.png

wKioL1dH8vWT9gcnAAKmA1hvfgE260.png返回值:成功,返回0;失败,返回-1,置错误码。

3.epoll_wait/epoll_pwait接收发生在被侦听的描述符上的,用户感兴趣的IO事件。

wKioL1dH8K-AUye_AABwqqeTD3c296.png

收集在epoll监控的事件中已经就绪的事件。

events:是分配好的epoll_event结构体数组,epoll将会把就绪的事件赋值到events数组中(events不可以是空指针,内核只负责把数据复制到这个events数组中)。

maxevents:告之内核这个events有多大,这个 maxevents的值不能小于创建epoll_create()时的size

timeout:是超时时间(毫秒)

    1.0表示轮询非阻塞,立即返回;

    2.-1将不确定,也有说法说是永久阻塞。

    3.大于0,以timeput事件轮询返回

返回值:

    1.成功,返回对应I/O上已准备好的文件描述符数

    2.0表示已超时。

    3.-1,发生错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
//初级版
#include<stdio.h>                                                               
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/epoll.h>
#define _SIZE_ 64
#define _BACKLOG_ 5
typedef  struct  fdBuf
{
     void  * _buf;
     int  _fd;
}fdBuf;
static  void  usage( const  char * proc)
{
     printf ( "%s [ip][port]" ,proc);
}
static  int  startup( char * ip, int  port)
{
     int  listen_sock=socket(AF_INET,SOCK_STREAM,0);
     if (listen_sock<0)
     {
         perror ( "socket" );
         exit (1);
     }
     struct  sockaddr_in local;
     local.sin_family=AF_INET;
     local.sin_port=htons(port);
     local.sin_addr.s_addr=inet_addr(ip);
     if (bind(listen_sock,( struct  sockaddr*)&local, sizeof (local))<0)
     {
         perror ( "bind" );
         exit (2);
     }
     if (listen(listen_sock,_BACKLOG_)<0)
     {
         perror ( "listen" );
         exit (3);
     }
     return  listen_sock;
}
int  sock_epoll( int  listen_sock)
{   
     //1.create fds instance
     int   ins=epoll_create(_SIZE_);
     if (ins<0)
     {
         perror ( "poll_create" );
         return  1;
     }
     struct  epoll_event ev;
     ev.events=EPOLLIN;
     ev.data.fd=listen_sock;
     int  i=0; //index
     fdBuf bufs[_SIZE_];
     for (i=0;i<_SIZE_;++i)
     {
         bufs[i]._fd=-1;
         bufs[i]._buf=NULL;
     }
     struct  epoll_event fds[_SIZE_]; //with bufs save buf 
     for (i=0;i<_SIZE_;++i)
     {
         fds[i].events=0;
         fds[i].data.fd=-1;
     }                                             
     epoll_ctl(ins,EPOLL_CTL_ADD,listen_sock,&ev);
     int  ret=-1;
     int  timeout=5000;
     struct  sockaddr_in remote;
     socklen_t len= sizeof (remote);
     ssize_t _s; //charnum
     while (1)
     {
         switch ((ret=epoll_wait(ins,fds,64,timeout)))
         {
             case  -1: //error
                 perror ( "epoll_wait" );
                 break ;
             case  0: //time out
                 printf ( "time is out\n" );
                 break ;
             default :
                 {
                     for (i=0;i<ret;++i)
                     {
                         //printf("%d",ret);
                         if (fds[i].data.fd==listen_sock)
                         {                                              
                             if (new_sock<0)
                             {
                                 perror ( "accept" );
                                 continue ;
                             }
                             ev.events=EPOLLIN;
                             ev.data.fd=new_sock;
                             epoll_ctl(ins,EPOLL_CTL_ADD,new_sock,&ev);
                         }
                         else  if
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值