基于epoll的聊天室程序

2023-11-09

epoll相对于poll和select这两个多路复用的I/O模型更加的高效。epoll的函数很简单,麻烦的地方在于水平出发和边沿触发。

用张图来说明下
20130713202857140

ET(边沿)只是在状态反转时触发,比如从不可读到可读。而LT(水平)就是如果可读,就会一直触发。所以在使用ET的时候要做一些额外的处理,比如可读的,一直把缓冲区读完,进入不可读状态,下次来数据才会触发。

下面贴出代码,只是一个简单的练习的例子
socketheads.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef SOCKETHEADS_H
#define SOCKETHEADS_H
 
 
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#endif //SOCKETHEADS_H

zepoll.h

C++
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
#ifndef EPOLL_H
#define EPOLL_H
 
#include <sys/epoll.h>
#include <unistd.h>
 
 
/**
* @brief The Epoll class 对epoll的封装
*/
class Epoll
{
public :
     /**
     *
     */
     enum EPOLL_OP { ADD = EPOLL_CTL_ADD , MOD = EPOLL_CTL_MOD , DEL = EPOLL_CTL_DEL } ;
     /**
     * 最大的连接数和最大的回传事件数
     */
     Epoll ( int _max = 30 , int maxevents = 20 ) ;
     ~ Epoll ( ) ;
     int create ( ) ;
     int add ( int fd , epoll_event * event ) ;
     int mod ( int fd , epoll_event * event ) ;
     int del ( int fd , epoll_event * event ) ;
     void setTimeout ( int timeout ) ;
     void setMaxEvents ( int maxevents ) ;
     int wait ( ) ;
     const epoll_event * events ( ) const ;
     const epoll_event & operator [ ] ( int index )
     {
         return backEvents [ index ] ;
     }
private :
     bool isValid ( ) const ;
     int max ;
     int epoll_fd ;
     int epoll_timeout ;
     int epoll_maxevents ;
     epoll_event * backEvents ;
} ;
 
#endif //EPOLL_H

zepoll.cpp

C++
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
#include "zepoll.h"
 
Epoll :: Epoll ( int _max , int maxevents ) : max ( _max ) ,
     epoll_fd ( - 1 ) ,
     epoll_timeout ( 0 ) ,
     epoll_maxevents ( maxevents ) ,
     backEvents ( 0 )
{
 
}
 
Epoll :: ~ Epoll ( )
{
     if ( isValid ( ) ) {
         close ( epoll_fd ) ;
     }
     delete [ ] backEvents ;
}
 
 
inline
bool Epoll :: isValid ( ) const
{
     return epoll_fd > 0 ;
}
 
inline
void Epoll :: setTimeout ( int timeout )
{
     epoll_timeout = timeout ;
}
 
inline
void Epoll :: setMaxEvents ( int maxevents )
{
     epoll_maxevents = maxevents ;
}
 
inline
const epoll_event * Epoll :: events ( ) const
{
     return backEvents ;
}
 
 
 
int Epoll :: create ( )
{
     epoll_fd = :: epoll_create ( max ) ;
     if ( isValid ( ) ) {
         backEvents = new epoll_event [ epoll_maxevents ] ;
     }
     return epoll_fd ;
}
 
int Epoll :: add ( int fd , epoll_event * event )
{
     if ( isValid ( ) ) {
         return :: epoll_ctl ( epoll_fd , ADD , fd , event ) ;
     }
     return - 1 ;
 
}
 
int Epoll :: mod ( int fd , epoll_event * event )
{
     if ( isValid ( ) ) {
         return :: epoll_ctl ( epoll_fd , MOD , fd , event ) ;
     }
     return - 1 ;
 
}
 
int Epoll :: del ( int fd , epoll_event * event )
{
     if ( isValid ( ) ) {
         return :: epoll_ctl ( epoll_fd , DEL , fd , event ) ;
     }
     return - 1 ;
}
 
int Epoll :: wait ( )
{
     if ( isValid ( ) ) {
         return :: epoll_wait ( epoll_fd , backEvents , epoll_maxevents , epoll_timeout ) ;
     }
     return - 1 ;
}

task.h

C++
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
/********************************************************************
* author 周翔
* e-mail 604487178@qq.com
* blog http://blog.csdn.net/zhx6044
**********************************************************************/
 
#ifndef TASK_H
#define TASK_H
 
#include <string>
#include <socketheads.h>
 
/**
* @brief The Task class 任务类
*/
class Task
{
public :
     typedef enum { CONNECT = 0 , DISCONNECT , TALKING } TASKFLAG ;
     Task ( const std :: string &message , TASKFLAG flag = TALKING ) ;
     const std :: string & getMessage ( ) const ;
     TASKFLAG getFlag ( ) const ;
     void setIP ( in_addr _ip ) ;
     int getS_fd ( ) const ;
 
     void setS_fd ( int _fd ) ;
 
 
     std :: string getData ( ) const ;
 
 
private :
     std :: string m_message ;
     TASKFLAG m_flag ;
     in_addr ip ;
     int s_fd ;
} ;
 
#endif // TASK_H

task.cpp

C++
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
/********************************************************************
* author 周翔
* e-mail 604487178@qq.com
* blog http://blog.csdn.net/zhx6044
**********************************************************************/
 
#include "task.h"
 
Task :: Task ( const std :: string &message , TASKFLAG flag ) :
     m_message ( message ) ,
     m_flag ( flag )
{
}
 
 
const std :: string & Task :: getMessage ( ) const
{
     return m_message ;
}
 
Task :: TASKFLAG Task :: getFlag ( ) const
{
     return m_flag ;
}
 
void Task :: setIP ( in_addr _ip )
{
     ip = _ip ;
}
 
int Task :: getS_fd ( ) const
{
     return s_fd ;
}
 
void Task :: setS_fd ( int _fd )
{
     s_fd = _fd ;
}
 
std :: string Task :: getData ( ) const
{
     std :: string re ;
     if ( m_flag == CONNECT ) {
         re = :: inet_ntoa ( ip ) + std :: string ( "----->" ) + "CONNECT!    " + m_message ;
     } else {
         if ( m_flag == DISCONNECT ) {
             re = :: inet_ntoa ( ip ) + std :: string ( "----->" ) + "DISCONNECT   " + m_message ; ;
         } else {
             re = :: inet_ntoa ( ip ) + std :: string ( "----->Talk:" ) + m_message ;
         }
     }
     return re ;
}

epoll_server.h

C++
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
#ifndef EPOLL_SERVER_H
#define EPOLL_SERVER_H
 
#include <map>
#include <list>
 
#include "zepoll.h"
#include "socketheads.h"
#include "task.h"
 
 
typedef std :: pair < int , in_addr > FDtoIP ;
 
/**
* @brief The Epoll_server class 服务器
*/
class Epoll_server
{
public :
     Epoll_server ( int port ) ;
     ~ Epoll_server ( ) ;
     int bind ( ) ;
     int listen ( ) ;
     void poweroff ( ) ;
     bool states ( ) const ;
private :
     enum    { BLOCKLOG = 5 } ;
 
     bool isValid ( ) const ;
 
     int acceptSocketEpoll ( ) ;
     int readSocketEpoll ( const epoll_event &ev ) ;
     int writeSocketEpoll ( const epoll_event &ev ) ;
 
     void doTask ( const Task &t ) ;
 
     int _port ;
     int server_socket_fd ;
     Epoll * _epoll ;
     sockaddr_in server_addr ;
     sockaddr_in client_addr ;
     epoll_event m_event ;
     bool on ;
     static int setNonblocking ( int socket_fd ) ;
     std :: list < FDtoIP > fd_IP ;
} ;
 
#endif //EPOLL_SERVER_H

epoll_server.cpp

C++
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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
#include "epoll_server.h"
 
#include <iostream>
 
 
//static char welcom[] = "welcom to my epoll_server";
//static char sorry[] = "Sorry! This is a simple demo,so not any function!";
//static char buf[BUFSIZ];
 
 
Epoll_server :: Epoll_server ( int port ) : _port ( port ) ,
     server_socket_fd ( - 1 ) ,
     _epoll ( 0 ) ,
     on ( true )
{
 
 
}
 
 
Epoll_server :: ~ Epoll_server ( )
{
     if ( isValid ( ) ) {
         :: close ( server_socket_fd ) ;
     }
     delete _epoll ;
 
}
 
 
inline
bool Epoll_server :: isValid ( ) const
{
     return server_socket_fd > 0 ;
}
 
 
inline
void Epoll_server :: poweroff ( )
{
     on = false ;
}
 
 
 
inline
bool Epoll_server :: states ( ) const
{
     return on ;
}
 
 
 
int Epoll_server :: setNonblocking ( int socket_fd )
{
     int opts ;
     opts = fcntl ( socket_fd , F_GETFL ) ;
     if ( opts < 0 ) {
         return - 1 ;
     } else
     {
         opts = opts | O_NONBLOCK ;
         if ( fcntl ( socket_fd , F_SETFL , opts ) < 0 ) {
 
             return - 1 ;
         }
     }
     return 0 ;
}
 
 
void Epoll_server :: doTask ( const Task &t )
{
     std :: list < FDtoIP > :: iterator ite = fd_IP . begin ( ) ;
     std :: list < FDtoIP > :: iterator ite1 = fd_IP . end ( ) ;
     for ( ; ite != fd_IP . end ( ) ; ++ ite ) {
         if ( ( * ite ) . first != t . getS_fd ( ) ) {
             memset ( &m_event , '\0' , sizeof ( m_event ) ) ;
             m_event . events = EPOLLOUT | EPOLLET ;
             Task * c = new Task ( t ) ;
             c -> setS_fd ( ( * ite ) . first ) ;
             m_event . data . ptr = static_cast < void * > ( c ) ;
             _epoll -> mod ( ( * ite ) . first , &m_event ) ;
         } else {
             ite1 = ite ;
         }
     }
     if ( t . getFlag ( ) == Task :: DISCONNECT ) {
         if ( ite1 != fd_IP . end ( ) ) {
             fd_IP . erase ( ite1 ) ;
         }
     }
}
 
/**
* @brief Epoll_server::acceptSocketEpoll 有用户接入
* @return
*/
int Epoll_server :: acceptSocketEpoll ( )
{
     socklen_t len = sizeof ( struct sockaddr_in ) ;
     int connect_fd ;
     while ( ( connect_fd = :: accept ( server_socket_fd ,
                                   ( struct sockaddr * ) ( &client_addr ) , &len ) ) > 0 ) {
         if ( setNonblocking ( connect_fd ) < 0 ) {
             :: close ( connect_fd ) ;
             continue ;
         }
         m_event . data . fd = connect_fd ;
         m_event . events = EPOLLIN | EPOLLET ;
         if ( _epoll -> add ( connect_fd , &m_event ) < 0 ) {
             :: close ( connect_fd ) ;
             continue ;
         } else {
 
             fd_IP . push_back ( FDtoIP ( connect_fd , client_addr . sin_addr ) ) ;
             Task t ( "come in" , Task :: CONNECT ) ;
             t . setIP ( client_addr . sin_addr ) ;
             t . setS_fd ( connect_fd ) ;
             doTask ( t ) ;
         }
     }
 
     if ( connect_fd == - 1 && errno != EAGAIN && errno != ECONNABORTED
             && errno != EPROTO && errno != EINTR ) {
         return - 1 ;
     }
     return 0 ;
}
 
 
int Epoll_server :: readSocketEpoll ( const epoll_event &ev )
{
     int n = 0 ;
     int nread = 0 ;
     char buf [ BUFSIZ ] = { '\0' } ;
     while ( ( nread = :: read ( ev . data . fd , buf + n , BUFSIZ - 1 ) ) > 0 ) {
         n += nread ;
     }
     if ( nread == - 1 && errno != EAGAIN ) {
         return - 1 ;
     }
 
     std :: list < FDtoIP > :: iterator ite = fd_IP . begin ( ) ;
     for ( ; ite != fd_IP . end ( ) ; ++ ite ) {
         if ( ( * ite ) . first == ev . data . fd ) {
             break ;
         }
     }
 
     if ( nread == 0 ) {
         strcpy ( buf , " disconet  left " ) ;
         Task t ( buf , Task :: DISCONNECT ) ;
         t . setIP ( client_addr . sin_addr ) ;
         t . setS_fd ( ( * ite ) . first ) ;
         doTask ( t ) ;
     } else {
         Task t ( buf , Task :: TALKING ) ;
         t . setIP ( client_addr . sin_addr ) ;
         t . setS_fd ( ( * ite ) . first ) ;
         doTask ( t ) ;
     }
 
     //    Task *t = new Task(buf,Task::DISCONNECT);
     //    t->setIP((*ite).second);
     //    t->setS_fd((*ite).first);
 
 
 
 
     // m_event.data.fd = ev.data.fd;
     // m_event.events = ev.events;
     return 0 ; //_epoll->mod(m_event.data.fd, &m_event);
}
 
 
int Epoll_server :: writeSocketEpoll ( const epoll_event &ev )
{
     Task * t = static_cast < Task * > ( ev . data . ptr ) ;
     const char * buf = t -> getData ( ) . data ( ) ;
     int nwrite = 0 , data_size = strlen ( buf ) ;
     int fd = t -> getS_fd ( ) ;
     int n = data_size ;
     delete t ;
     while ( n > 0 ) {
         nwrite = :: write ( fd , buf + data_size - n , n ) ;
         if ( nwrite < 0 ) {
             if ( nwrite == - 1 && errno != EAGAIN ) {
                 return - 1 ;
             }
             break ;
         }
         n -= nwrite ;
     }
 
     memset ( &m_event , '\0' , sizeof ( m_event ) ) ;
     // m_event.events &= ~EPOLLOUT;
     m_event . events = EPOLLIN | EPOLLET ;
     m_event . data . fd = fd ;
     if ( _epoll -> mod ( fd , &m_event ) < 0 ) {
         :: close ( m_event . data . fd ) ;
         return - 1 ;
     }
     return 0 ;
}
 
/**
* @brief Epoll_server::bind
* @return
*/
int Epoll_server :: bind ( )
{
     server_socket_fd = socket ( AF_INET , SOCK_STREAM , 0 ) ;
     if ( server_socket_fd < 0 ) {
         return - 1 ;
     }
 
     setNonblocking ( server_socket_fd ) ;
 
     _epoll = new Epoll ( ) ;
     if ( _epoll -> create ( ) < 0 ) {
         return - 1 ;
     }
     memset ( &m_event , '\0' , sizeof ( m_event ) ) ;
     m_event . data . fd = server_socket_fd ;
     m_event . events = EPOLLIN | EPOLLET ;
     _epoll -> add ( server_socket_fd , &m_event ) ;
 
     memset ( &server_addr , 0 , sizeof ( server_addr ) ) ;
     server_addr . sin_family = AF_INET ;
     server_addr . sin_addr . s_addr = htonl ( INADDR_ANY ) ;
     server_addr . sin_port = htons ( _port ) ;
 
     return :: bind ( server_socket_fd , ( struct sockaddr * ) ( &server_addr ) , sizeof ( struct sockaddr ) ) ;
 
}
 
 
int Epoll_server :: listen ( )
{
     if ( isValid ( ) ) {
         if ( :: listen ( server_socket_fd , BLOCKLOG ) < 0 ) {
             return - 1 ;
         } else {
             int num ;
             while ( on ) {
                 num = _epoll -> wait ( ) ;
                 for ( int i = 0 ; i < num ; ++ i ) {
                     /**
                     * 接受连接的连接,把她加入到epoll中
                     */
                     if ( ( * _epoll ) [ i ] . data . fd == server_socket_fd ) {
                         if ( acceptSocketEpoll ( ) < 0 ) {
                             break ;
                         }
                         continue ;
 
                     }
                     /**
                     * EPOLLIN event
                     */
                     if ( ( * _epoll ) [ i ] . events & EPOLLIN ) {
                         if ( readSocketEpoll ( ( * _epoll ) [ i ] ) < 0 ) {
                             break ;
                         }
                         continue ;
 
 
                     }
 
                     /**
                     * EPOLLOUT event
                     */
                     if ( ( * _epoll ) [ i ] . events & EPOLLOUT ) {
                         if ( writeSocketEpoll ( ( * _epoll ) [ i ] ) < 0 ) {
                             break ;
                         }
 
                     }
                 }
             }
         }
     }
     return - 1 ;
}

main.cpp

C++
1
2
3
4
5
6
7
8
9
10
11
12
#include "epoll_server.h"
#include <iostream>
 
int main ( int /*argc*/ , char const * * /*argv[]*/ )
{
     std :: cout << "server" << std :: endl ;
     Epoll _server s ( 18090 ) ;
     if ( s . bind ( ) < 0 ) {
         return - 1 ;
     }
     return s . listen ( ) ;
}

客户端用qt简单的写了一个
20130713204007843
客户端服务端代码:epoll_chatroom.zip


FROM: http://love.junzimu.com/archives/2660


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于epoll的聊天室程序 的相关文章

  • linux AIO (异步IO) 那点事儿

    在高性能的服务器编程中 IO 模型理所当然的是重中之重 需要谨慎选型的 对于网络套接字 我们可以采用epoll 的方式来轮询 尽管epoll也有一些缺陷 但总体来说还是很高效的 尤其来大量套接字的场景下 但对于Regular File 来说
  • ipv6 socket bind 失败 - accept_dad

    file proc sys net ipv6 conf interface accept dad variable net ipv6 conf interface accept dad Official reference Whether
  • 网络层:IP协议

    本博文分享的是网络层的IP协议 从IP协议的基本概念 协议格式开始分析并分享出来 IP协议的基本概念 不同于讨论TCP UDP时只讨论通信主机之间的关系 在讨论IP协议中 会加上主机之间的网络来一起进行讨论分析 主机 一般配有IP地址 路由
  • whois命令常见用法

    whois命令常见用法 whois命令简介 安装whois Windows使用whois Linux安装whois whois常见用法 Linux下whois查询域名注册信息 whois命令简介 whois就是一个用来查询域名是否已经被注册
  • C++在线五子棋对战(网页版)项目:websocket协议

    目标 认识理解websocket协议 websocket切换过程和websocket协议格式 认识和学会使用websocketpp库常用接口 了解websocketpp库搭建服务器流程 认识和学会使用websocketpp库bin接口 最后
  • webbench剖析

    webbench 其为linux上一款web性能压力测试工具 它最多可以模拟3万个并发连接数来测试服务器压力 其原理为fork多个子进程 每个子进程都循环做web访问测试 子进程将访问的结果通过管道告诉父进程 父进程做最终结果统计 其主要原
  • 【Linux网络(C++)】——网络套接字(TCP/UDP编程模型)多进程,多线程,线程池服务器开发(画图解析)

    目录 一 套接字基本概念 IP地址 TCP和UDP协议 端口号 端口号vs 进程pid 网络字节序 本地字节序转换成网络字节序 网络字节序转换为本地字节序 二 套接字的基本操作 socket的创建 域 domain 类型 type 协议 P
  • 高并发的epoll+线程池,业务在线程池内

    epoll是linux下高并发服务器的完美方案 因为是基于事件触发的 所以比select快的不只是一个数量级 单线程epoll 触发量可达到15000 但是加上业务后 因为大多数业务都与数据库打交道 所以就会存在阻塞的情况 这个时候就必须用
  • linux 网络编程---->多路复用:select实例!

    好吧 我承认找了好久 网上都没有像样的完整的实例 然后自己参照书自己写一个吧 gt server 端代码 gt server c include
  • 基于epoll的聊天室程序

    epoll相对于poll和select这两个多路复用的I O模型更加的高效 epoll的函数很简单 麻烦的地方在于水平出发和边沿触发 用张图来说明下 ET 边沿 只是在状态反转时触发 比如从不可读到可读 而LT 水平 就是如果可读 就会一直
  • Linux网络和安全:配置、远程访问与防御指南

    文章目录 Linux 网络和安全 引言 网络配置 IP地址配置 配置网络接口 防火墙设置 安全性加强 Linux网络配置及端口管理 网络配置命令 端口管理 防火墙和安全性设置 防火墙管理工具 安全性设置 Linux远程访问技术 SSH和VP
  • Linux网络编程一步一步学 - 目录(汇总)zhuan

    非常好的关于Linux网络编程的文章 我也是无意中在别人的博客里发现的 在网上搜了一下 这类的文章总共还有很多篇 最后我找到了原作者的姓名 周立发 以及作者的博客空间 本人坚决支持原创 在此将其文章进行了汇总 并且空间首页加入了他的博客链接
  • 【网络自定向下的学习】——TCP3次握手和4次挥手详解

    目录 前言 一 可靠数据传输 1 确认应答机制 2 超时重传机制 二 建立连接 三次握手 1 建立连接的过程 2 为什么会有三次握手 3 三次握手可以携带数据吗 4 什么是半连接队列 三 断开连接 4次挥手 1 4次挥手的过程 2 为什么连
  • linux下异步RPC的阶段性总结-非阻塞SOCKET客户端

    尽可能使用非阻塞socket int flags s flags fcntl fd F GETFL 0 if flags 1 close fd return 1 flags O NONBLOCK s fcntl fd F SETFL fla
  • 组播技术

    1 概述 1 1 产生背景 传统的IP通信有两种方式 一种是在源主机与目的主机之间点对点的通信 即单播 另一种是在源主机与同一网段中所有其它主机之间点对多点的通信 即广播 如果要将信息发送给多个主机而非所有主机 若采用广播方式实现 不仅会将
  • linux非阻塞socket教程

    本文并非解释什么是非阻塞socket 也不是介绍socket API的用法 取而代替的是让你感受实际工作中的代码编写 虽然很简陋 但你可以通过man手册与其它资源非富你的代码 请注意本教程所说的主题 如果细说 内容可以达到一本书内容 你会发
  • 【IP协议(一)】——IP数据报格式及其含义,IP数据报的切分

    个人主页 努力学习的少年 版权 本文由 努力学习的少年 原创 在CSDN首发 需要转载请联系博主 如果文章对你有帮助 欢迎关注 点赞 收藏 一键三连 和订阅专栏哦 IP数据报格式 版本 占4位 指ip协议的版本 首部长度 表示IP数据报中报
  • 【网络自定向下学习】——TCP报文段的详细解析

    个人主页 努力学习的少年 版权 本文由 努力学习的少年 原创 在CSDN首发 需要转载请联系博主 如果文章对你有帮助 欢迎关注 点赞 收藏 一键三连 和订阅专栏哦 目录 一 Tcp报文段的结构 二 首部长度 三 窗口大小 四 序列号和确认序
  • poll()函数详解

    poll提供的功能与select类似 不过在处理流设备时 它能够提供额外的信息 include
  • 超级详细Tcpdump 的用法

    1 抓取回环网口的包 tcpdump i lo 2 防止包截断 tcpdump s0 3 以数字显示主机及端口 tcpdump n 第一种是关于类型的关键字 主要包括host net port 例如 host 210 27 48 2 指明

随机推荐

  • 旋转编码器简介

    旋转编码器如图 编码器具有左旋 右旋 按下三个功能 4 5脚是中间按下去的开关接线 1 2 3脚一般中间2脚接地 1 3脚上拉电阻后 当左转 右转旋纽时 在1 3脚就有脉冲信号输出了 输出1为高电平时 输出2出现一个高电平 这时开关就是向顺
  • RocektMQ社区"每周直播分享第8期"如约而至

    各位同学 RocektMQ社区 每周直播分享第8期 如约而至 分享题目 RocketMQ消息的过滤和重试实现原理详解 直播方式 钉钉群直播方式 群号 21791227 分享时间 2019 01 24 20 00 21 30 本周四 分享讲师
  • Apache WEB 服务器企业实战

    万维网 WORLD WIDE WEB WWW 服务器 也称之为 WEB 服务器 主要功能 是提供网上信息浏览服务 WWW 是 Internet 的多媒体信息查询工具 是 Internet 上 飞快发展的服务 也是目前用的最广泛的服务 正是因
  • kafka查看topic中的数据_实战!Kafka Manager能统计出Topic中的记录条数吗?

    问题描述 今天现场实施同事说Kafka Manager上显示有3500w条记录 但使用我们的平台落地后 一统计发现只有2200w条记录 这是不是说明我们的平台存在丢数据的可能 经了解 对接方是通过如下界面来判断topic中的记录条数的 上图
  • 常见Redis使用问题

    一 lettuce使用问题 1 问题描述 Redis Cluster集群 当master宕机 主从切换 客户端报错 timed out 2 原因 SpringBoot2 X版本开始Redis默认的连接池都是采用的Lettuce 当节点发生改
  • 原理图转换PCB网络丢失常见错误:PCB封装焊盘与原理图管脚号不一致

    小白在画PCB时 当把原理图画好后 生成PCB是有时会发现丢失部分网络 明明原理图和封装没错误怎么还会没网络 明明在原理图U1 16个管脚都有电气网络 怎么到PCB怎么没有了 这时候很有可能是PCB的焊盘封装与原理图的管脚号不一致导致 原理
  • Unable to negotiate with 10.11.81 port 8235: no matching host key type found. Their offer: ssh-rsa

    mac电脑重装系统 去官网下载了最新的git安装 一路next下来 打开bash按老路子设置 生成公钥 git config global user name yourname git config global user email yo
  • 微信小程序Day2笔记

    1 WXML模板语法 1 数据绑定 数据绑定的基本原则 在data中定义数据 在WXML中使用数据 2 在data中定义页面的数据 在页面对应的 js文件中 把数据定义到data对象中 3 Mustache语法的格式 把data中的数据绑定
  • 网络协议介绍

    网络层的功能 定义了基于IP协议的逻辑地址 连接不同的媒介类型 选择数据通过网络的最佳路径 IP数据包格式 协议字段 ICMP协议 Internet控制报文协议 1 ICMP是一个 错误侦测与回馈机制 2 通过IP数据包封装的 3 用来发送
  • vue中安装和使用Dplayer视频播放器

    1 下载 npm下载 npm install dplayer s npm i hls js s yarn下载 yarn add dplayer yarn add hls js 2 使用
  • cpolar如何配置固定TCP地址

    通常 每次启动 TCP 隧道时都会随机分配远程TCP地址和端口 它会在24小时后随机变化 对于生产环境的服务或经常访问的TCP地址 很不方便 您通常需要一个稳定的 固定端口的远程TCP地址 为此 让我们来配置一个永久固定的公网TCP地址 首
  • Visual Studio 2022 版本 17.5 预览版 正式上线,有你期待的功能吗?

    目录 此次发布的 Visual Studio 2022 版本 17 5 预览版中的新增功能摘要 C 代码搜索和导航 Git 工具 Markdown 调试和诊断 一元搜索汇报 集成终端中的 ASP NET 输出 按正则表达式着色制表符 编辑
  • 高数--猴博士爱讲课

    重点章节 导数 微分 积分 梯度 泰勒展开公式 第一课 求极限 求极限 函数 例一 试求 l i m x
  • vue3+element-plus封装表格

    1 封装表格 封装的表格如何使用插槽可以到这参考 vue3封装element plus表格使用插槽 小了黑了兔 的博客 CSDN博客
  • JMeter学习笔记15-如何用JMeter做接口测试

    本文介绍JMeter如何做web service测试 一般来说web服务 一般指的是HTTP请求相关的内容 这里就介绍一下如何利用JMeter做基于HTTP的web接口测试 接口也叫API Application Programming I
  • 爬虫技术-字体反爬

    文本混淆章节 1 文本混淆简介 简单而言就是利用前端技术干扰 页面可以正常展示 而使用爬虫下载后无法提取正常的数据 1 1 常见的干扰方式 字体反爬 2 字体反爬 2 1 字体反爬简介 在 CSS3 之前 Web 开发者必须使用用户计算机上
  • Vue3+Vite+Ts的Axios企业级封装+本地存储封装

    前言 实际项目开发中 向后台发请求 vue相关项目 都是用axios 不会用ajax 不会为了ajax单独去引入jquery axios官网 http www axios js com 第一步 下载依赖axios npm i axios s
  • 关于java内访问流式接口处理

    我找了一圈 没找到合适得方法 知识面得欠缺 会让遇到问题没有办法 最后联系百度智能才知道怎么做 给百度智能AI一个好评 我也是才知道一般的写法都是OKhttp OkHttp 会阻塞直到所有响应都回来后才会整体返回 建议您用原生HttpURL
  • idea搭建Spark开发环境

    最近在公司换了一个项目组 做Spark项目的 于是开始学Spark 版本
  • 基于epoll的聊天室程序

    epoll相对于poll和select这两个多路复用的I O模型更加的高效 epoll的函数很简单 麻烦的地方在于水平出发和边沿触发 用张图来说明下 ET 边沿 只是在状态反转时触发 比如从不可读到可读 而LT 水平 就是如果可读 就会一直