??xml version="1.0" encoding="utf-8" standalone="yes"?>女同久久,四虎国产精品免费久久5151,久久精品国产亚洲AV无码娇色http://m.shnenglu.com/qinqing1984/category/10072.htmlzh-cnSat, 30 Sep 2023 22:54:13 GMTSat, 30 Sep 2023 22:54:13 GMT60ZX509证书的n份认证思考小l?/title><link>http://m.shnenglu.com/qinqing1984/archive/2023/09/30/230117.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Sat, 30 Sep 2023 00:00:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2023/09/30/230117.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/230117.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2023/09/30/230117.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/230117.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/230117.html</trackback:ping><description><![CDATA[<div> <div style="text-align: center;"><img src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/x509-three-auths-2.jpg" width="1232" height="638" alt="" /></div>   有单向、双向、三?U认证方式,前两者必L查时间戳以防重放dQ单向因为只有一个消息传递,如果仅靠一ơ性随机数是无法判断消息是否重放。双向有两个消息传递,一来一回,仅靠一ơ性随机数只能到发响应那方的重放。最后者则不必Q可仅通过一ơ性随机数自己是否遭遇重放攻击,因ؓ接收W二个消息的那方Q通过判断W二个消息中随机数是否等于自己先前已发送第一个消息中的那个,若不{于则ؓ重放Q若{于则发W三个确认消息给ҎQ对Ҏ到ƈ判断认消息中的随机数是否等于先前它已发送第二个消息中的随机敎ͼ若等于则说明W它收到的第一个消息的是另一方发送的即非重放Q否则ؓ重放。因此三向认证可不必同步双方旉。但正因Z强制查时间戳而可能导?span style="color: #ff00ff; font-size: 12pt;">中间人攻?/span>Q假N信双方为A、BQ中间h为CQ攻L骤如?/div> <div> <strong>1</strong>. C与B认证Ӟ发送先前已截获的A到Bh消息lB</div> <div> <strong>2</strong>. 截获q存储B到A的响应消息xQ但不{发,开始与A认证</div> <div> <strong>3</strong>. 收到A的请求消息后Q解密x取出其中的随机数Rb作ؓ响应lA消息中的随机敎ͼ用自q钥签|整个消息后发给A</div> <div> <strong>4</strong>. 收到q{发A的确认消息给B</div> <div>以上完成后,Cp冒充A与B通信了?span style="color: #ff6600;">一U简单的改进Ҏ</span>是先用对方的公钥加密消息中的随机敎ͼ再用自己的私钥签|整个消息。关于网l协议的安全性分析,LҎ是Ş式化分析Q可以借助相关工具来验证找出漏z?/div><img src ="http://m.shnenglu.com/qinqing1984/aggbug/230117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2023-09-30 08:00 <a href="http://m.shnenglu.com/qinqing1984/archive/2023/09/30/230117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用HiRedis实现自动重连Redishttp://m.shnenglu.com/qinqing1984/archive/2021/02/25/217619.html春秋十二?/dc:creator>春秋十二?/author>Thu, 25 Feb 2021 07:51:00 GMThttp://m.shnenglu.com/qinqing1984/archive/2021/02/25/217619.htmlhttp://m.shnenglu.com/qinqing1984/comments/217619.htmlhttp://m.shnenglu.com/qinqing1984/archive/2021/02/25/217619.html#Feedback0http://m.shnenglu.com/qinqing1984/comments/commentRss/217619.htmlhttp://m.shnenglu.com/qinqing1984/services/trackbacks/217619.html主要思\
 1. 首次q接时调用redisConnectWithTimeout或redisConnectUnixWithTimeoutq接Redis服务端,若成功则保存q回的redisContextQ假设ؓctx
 2. 发送命令数据后获取响应Q如果是pipeling模式则调用redisGetReply获取响应Q再查redisContext中的错误码,如果为网l出错或关闭Q则不置位ctx REDIS_CONNECTED标志
 3. 在下ơ发送数据时Q先查ctx否置位了REDIS_CONNECTED标志Q若没有则调用redisReconnect重连Redis服务?br />
实现代码
 自动q接
 1 int redis_auto_connect(CBED_REDIS *redis)
 2 {
 3     if(NULL==redis->ctx){
 4         redisContext *ctx;
 5         if(redis->type == CONN_TCP)
 6             ctx = redisConnectWithTimeout(redis->conn.tcp.ip, redis->conn.tcp.port, redis->timeout_conn);
 7         else
 8             ctx = redisConnectUnixWithTimeout(redis->conn.unix.path, redis->timeout_conn);
 9         
10         if(NULL==ctx){
11             zlog_fatal(c_redis, "redis allocate context fail");
12             return -1;
13             
14         }else if(ctx->err){
15             zlog_fatal(c_redis, "redis connection %s:%d error: %s", 
16                         redis->type==CONN_TCP?redis->conn.tcp.ip:redis->conn.unix.path, 
17                         redis->type==CONN_TCP?redis->conn.tcp.port:0, ctx->errstr);
18             redisFree(ctx);
19             return -1;
20         }
21         
22         if(REDIS_ERR==redisSetTimeout(ctx, redis->timeout_rw)){
23             zlog_fatal(c_redis, "redis set rw timeout error: %s", ctx->errstr);
24             redisFree(ctx);
25             return -1;
26         }
27         
28         redis->ctx = ctx;
29         if(redis_auth(redis)){
30             redisFree(ctx);
31             redis->ctx = NULL;
32             return -1;
33         }
34         
35     }    else if(!(redis->ctx->flags & REDIS_CONNECTED)){
36         int retry = redis->reconn_max, n = 0;
37         do {
38             if(REDIS_OK==redisReconnect(redis->ctx)){
39                 return redis_auth(redis);
40             }
41             
42             zlog_warn(c_redis, "redis reconnect %d error: %s", ++n, redis->ctx->errstr);    
43             sleep(redis->reconn_interval); //reconn_interval default is 3 seconds
44             
45         }while(--retry > 0);
46         
47         zlog_error(c_redis, "redis reconnect exceed max num %d", redis->reconn_max);
48         return -1;
49     }
50 
51     return 0;
52 }
 
 发送时查错误码
 1 static int redis_bulk_get_reply(CBED_REDIS *redis)
 2 {
 3     redisReply *r;
 4     int i = 0;        
 5     int num = redis->cmd_num;
 6     redis->cmd_num = 0;
 7 
 8     for(; i<num; ++i){
 9         if(REDIS_OK==redisGetReply(redis->ctx, (void**)&r)){
10             if(r->type == REDIS_REPLY_ERROR){
11                 zlog_error(c_redis, "redis get reply error: %.*s", r->len, r->str);
12                 freeReplyObject(r);
13                 return -1;
14             }
15             freeReplyObject(r);
16         
17         }else{
18             if(redis->ctx->err==REDIS_ERR_IO||redis->ctx->err==REDIS_ERR_EOF)
19                 redis->ctx->flags &= ~REDIS_CONNECTED;
20             zlog_fatal(c_redis, "redis get reply fail: %s", redis->ctx->errstr);
21             return -1;
22         }
23     }
24 
25     return 0;
26 }
27 
28 int redis_send(CBED_REDIS *redis, unsigned char *data, unsigned int size, int force)
29 {
30     if(redis_auto_connect(redis))
31         return -1;
32 
33     int i;
34     
35     if(redis->max_cmd_num > 1){ //pipelining
36         for(i=0; i<redis->queue_num; ++i){
37             if(REDIS_ERR == redisAppendCommand(redis->ctx, "RPUSH %s %b", redis->queue[i], data, size)) {
38                 zlog_fatal(c_redis, "redis append command rpush %s len %u fail: %s", redis->queue[i], size, redis->ctx->errstr);
39                 return -1;
40             }
41             
42             ++redis->cmd_num;
43             if((!force && redis->cmd_num==redis->max_cmd_num) || force){
44                 if(redis_bulk_get_reply(redis))
45                     return -1;
46             }
47         }
48         
49     }else{
50         for(i=0; i<redis->queue_num; ++i){
51             redisReply *r = redisCommand(redis->ctx, "RPUSH %s %b", redis->queue[i], data, size);
52             if(NULL==r){
53                 if(redis->ctx->err==REDIS_ERR_IO||redis->ctx->err==REDIS_ERR_EOF)
54                     redis->ctx->flags &= ~REDIS_CONNECTED;
55                 zlog_fatal(c_redis, "redis command rpush %s len %u fail: %s", redis->queue[i], size, redis->ctx->errstr);
56                 return -1;
57             }
58             
59             if(r->type == REDIS_REPLY_ERROR){
60                 zlog_error(c_redis, "redis reply rpush %s len %u error: %.*s", redis->queue[i], size, r->len, r->str);
61                 freeReplyObject(r);
62                 return -1;
63             }
64 
65             freeReplyObject(r);
66         }
67     }
68 
69     return 0;
70 }


]]>
ZENet实现可靠UDP通信的同步模?/title><link>http://m.shnenglu.com/qinqing1984/archive/2020/05/04/217279.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Mon, 04 May 2020 11:08:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2020/05/04/217279.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/217279.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2020/05/04/217279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/217279.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/217279.html</trackback:ping><description><![CDATA[<span style="font-size: 13pt;"><strong>场景说明</strong></span><br />    选择ENet代替TCP用于q环境(通常丢包率高)的数据传输,提高可靠性及传输效率。ؓ了说明怎样正确有效地应用ENetQ本文按照TCP C/S同步通信的流E作了对应的接口装实现Q取库名?span style="color: #ff0000;"><strong>rudp</strong></span>?br /> <br /> <span style="font-size: 13pt;"><strong>接口对照<br /> </strong></span>   左边为rudp库的APIQ右边ؓ标准的Berkeley套接字API。rudp库所有API前缀为rudpQrudp_listen和rudp_accept仅用于服务端Qrudp_connect和rudp_disconnect仅用于客LQ其它接口共用于两端Q其中rudp_send调用rudp_sendmsg实现Qrudp_recv调用rudp_recvmsg实现?br />                    <img src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/rudp_vs_standard_socket_api.png" alt="" /><br /> <strong style="font-size: 13pt;"><br /> 具体实现</strong><br />    所有接口遵循Berkeley套接字接口的语义Qؓ单v见,错误描述输出到标准错误流?br />    ◆ <strong style="font-size: 12pt;">监听</strong>Q成功返?Q失败返?1<br /> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 14px;padding-top: 4px;width: 98%;word-break:break-all"> <div><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #008080; "> 1</span> <span style="color: #0000FF; ">int</span> <strong style="color: #993366; font-size: 12pt;">rudp_listen</strong>(<span style="color: #0000FF; ">const</span> <span style="color: #0000FF; ">char</span> *ip, <span style="color: #0000FF; ">int</span> port, ENetHost **host)<br /> <span style="color: #008080; "> 2</span> {    <br /> <span style="color: #008080; "> 3</span>     ENetAddress address;    <br /> <span style="color: #008080; "> 4</span> <br /> <span style="color: #008080; "> 5</span>     <span style="color: #0000FF; ">if</span>(!strcmp(ip, "*"))<br /> <span style="color: #008080; "> 6</span>            ip = "0.0.0.0";<br /> <span style="color: #008080; "> 7</span> <br /> <span style="color: #008080; "> 8</span>     <span style="color: #0000FF; ">if</span>(enet_address_set_host_ip(&address, ip)){<br /> <span style="color: #008080; "> 9</span>           fprintf(stderr, "enet_address_set_host_ip %s fail", ip);<br /> <span style="color: #008080; ">10</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">11</span>     }<br /> <span style="color: #008080; ">12</span>     <br /> <span style="color: #008080; ">13</span>     address.port = port;<br /> <span style="color: #008080; ">14</span>     <br /> <span style="color: #008080; ">15</span>     assert(host);<br /> <span style="color: #008080; ">16</span>     *host = enet_host_create(&address, 1, 1, 0, 0);<br /> <span style="color: #008080; ">17</span>     <span style="color: #0000FF; ">if</span>(NULL==*host){<br /> <span style="color: #008080; ">18</span>           fprintf(stderr, "enet_host_create %s:%d fail", address.host, address.port);<br /> <span style="color: #008080; ">19</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">20</span>     }<br /> <span style="color: #008080; ">21</span> <br /> <span style="color: #008080; ">22</span>     <span style="color: #0000FF; ">int</span> size = 1024*1024*1024;<br /> <span style="color: #008080; ">23</span>     <span style="color: #0000FF; ">if</span>(enet_socket_set_option((*host)->socket, ENET_SOCKOPT_RCVBUF, size)){<br /> <span style="color: #008080; ">24</span>            fprintf(stderr, "enet set server socket rcvbuf %d bytes fail", size);<br /> <span style="color: #008080; ">25</span>     }<br /> <span style="color: #008080; ">26</span> <br /> <span style="color: #008080; ">27</span>     <span style="color: #0000FF; ">return</span> 0;<br /> <span style="color: #008080; ">28</span> }</div> </div> <br />    ◆ <strong style="font-size: 12pt;">接受q接</strong>Q成功返?Q失败返?1<br /> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 14px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #008080; "> 1</span> <span style="color: #0000FF; ">int</span> <strong style="font-size: 12pt; color: #993366;">rudp_accept</strong>(ENetHost *host, unsigned <span style="color: #0000FF; ">int</span> timeout, ENetPeer **peer)<br /> <span style="color: #008080; "> 2</span> {<br /> <span style="color: #008080; "> 3</span>     <span style="color: #0000FF; ">int</span> ret;<br /> <span style="color: #008080; "> 4</span>     ENetEvent <span style="color: #0000FF; ">event</span>;<br /> <span style="color: #008080; "> 5</span> <br /> <span style="color: #008080; "> 6</span>     ret = enet_host_service(host, &<span style="color: #0000FF; ">event</span>, timeout);<br /> <span style="color: #008080; "> 7</span>     <span style="color: #0000FF; ">if</span>(ret > 0){        <br /> <span style="color: #008080; "> 8</span>         <span style="color: #0000FF; ">if</span>(<span style="color: #0000FF; ">event</span>.type != ENET_EVENT_TYPE_CONNECT){<br /> <span style="color: #008080; "> 9</span>             <span style="color: #0000FF; ">if</span>(<span style="color: #0000FF; ">event</span>.type == ENET_EVENT_TYPE_RECEIVE)<br /> <span style="color: #008080; ">10</span>                 enet_packet_destroy(<span style="color: #0000FF; ">event</span>.packet);<br /> <span style="color: #008080; ">11</span>             fprintf(stderr, "enet_host_service event type %d is not connect", <span style="color: #0000FF; ">event</span>.type);<br /> <span style="color: #008080; ">12</span>             <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">13</span>         }<br /> <span style="color: #008080; ">14</span>         <br /> <span style="color: #008080; ">15</span>         assert(peer);<br /> <span style="color: #008080; ">16</span>         *peer = <span style="color: #0000FF; ">event</span>.peer;<br /> <span style="color: #008080; ">17</span>         <br /> <span style="color: #008080; ">18</span>     }<span style="color: #0000FF; ">else</span> <span style="color: #0000FF; ">if</span>(0==ret){<br /> <span style="color: #008080; ">19</span>         fprintf(stderr, "enet_host_service timeout %d", timeout);<br /> <span style="color: #008080; ">20</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">21</span>         <br /> <span style="color: #008080; ">22</span>     }<span style="color: #0000FF; ">else</span>{<br /> <span style="color: #008080; ">23</span>         fprintf(stderr, "enet_host_service fail");<br /> <span style="color: #008080; ">24</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">25</span>     }    <br /> <span style="color: #008080; ">26</span> <br /> <span style="color: #008080; ">27</span>     <span style="color: #0000FF; ">return</span> 0;<br /> <span style="color: #008080; ">28</span> }</div>    <br />    ◆ <strong style="font-size: 12pt;">建立q接</strong>Q成功返?Q失败返?1Qconn_timeout是连接超Ӟrw_timeout是收发超Ӟ单位为毫U?br /> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 14px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #008080; "> 1</span> <span style="color: #0000FF; ">int</span> <strong style="color: #993366; font-size: 12pt;">rudp_connect</strong><span style="font-size: 12pt;">(</span><span style="color: #0000FF; ">const</span> <span style="color: #0000FF; ">char</span> *srv_ip, <span style="color: #0000FF; ">int</span> srv_port, unsigned <span style="color: #0000FF; ">int</span> conn_timeout, unsigned <span style="color: #0000FF; ">int</span> rw_timeout, ENetHost **host, ENetPeer **peer)<br /> <span style="color: #008080; "> 2</span> {    <br /> <span style="color: #008080; "> 3</span>     assert(host);<br /> <span style="color: #008080; "> 4</span>     *host = enet_host_create(NULL, 1, 1, 0, 0);<br /> <span style="color: #008080; "> 5</span>     <span style="color: #0000FF; ">if</span>(NULL==*host){<br /> <span style="color: #008080; "> 6</span>         fprintf(stderr, "enet_host_create fail");<br /> <span style="color: #008080; "> 7</span>         <span style="color: #0000FF; ">goto</span> fail;<br /> <span style="color: #008080; "> 8</span>     }<br /> <span style="color: #008080; "> 9</span>     <span style="color: #0000FF; ">if</span>(enet_socket_set_option((*host)->socket, ENET_SOCKOPT_RCVBUF, 1024*1024*1024)){<br /> <span style="color: #008080; ">10</span>            fprintf(stderr, "enet set server socket rcvbuf 1M bytes fail");<br /> <span style="color: #008080; ">11</span>     }<br /> <span style="color: #008080; ">12</span>     <br /> <span style="color: #008080; ">13</span>     ENetAddress srv_addr;<br /> <span style="color: #008080; ">14</span>     <span style="color: #0000FF; ">if</span>(enet_address_set_host_ip(&srv_addr, srv_ip)){<br /> <span style="color: #008080; ">15</span>         fprintf(stderr, "enet_address_set_host_ip %s fail", srv_ip);<br /> <span style="color: #008080; ">16</span>         <span style="color: #0000FF; ">goto</span> fail;<br /> <span style="color: #008080; ">17</span>     }<br /> <span style="color: #008080; ">18</span>     srv_addr.port = srv_port;<br /> <span style="color: #008080; ">19</span>     <br /> <span style="color: #008080; ">20</span>     assert(peer);<br /> <span style="color: #008080; ">21</span>     *peer = enet_host_connect(*host, &srv_addr, 1, 0); <br /> <span style="color: #008080; ">22</span>     <span style="color: #0000FF; ">if</span>(*peer==NULL){<br /> <span style="color: #008080; ">23</span>             fprintf(stderr, "enet_host_connect %s:%d fail", srv_ip, srv_port);<br /> <span style="color: #008080; ">24</span>         <span style="color: #0000FF; ">goto</span> fail;<br /> <span style="color: #008080; ">25</span>     }<br /> <span style="color: #008080; ">26</span> <br /> <span style="color: #008080; ">27</span>     enet_peer_timeout(*peer, 0, rw_timeout, rw_timeout);<br /> <span style="color: #008080; ">28</span>     <br /> <span style="color: #008080; ">29</span>     <span style="color: #0000FF; ">int</span> cnt = 0;<br /> <span style="color: #008080; ">30</span>     ENetEvent <span style="color: #0000FF; ">event</span>;<br /> <span style="color: #008080; ">31</span> <br /> <span style="color: #008080; ">32</span>     <span style="color: #0000FF; ">while</span>(1){<br /> <span style="color: #008080; ">33</span>         ret = enet_host_service(*host, &<span style="color: #0000FF; ">event</span>, 1);<br /> <span style="color: #008080; ">34</span>         <span style="color: #0000FF; ">if</span>(ret == 0){    <br /> <span style="color: #008080; ">35</span>             <span style="color: #0000FF; ">if</span>(++cnt >= conn_timeout){ <br /> <span style="color: #008080; ">36</span>                    fprintf(stderr, "enet_host_service timeout %d", conn_timeout);<br /> <span style="color: #008080; ">37</span>                 <span style="color: #0000FF; ">goto</span> fail;<br /> <span style="color: #008080; ">38</span>             }<br /> <span style="color: #008080; ">39</span>         <br /> <span style="color: #008080; ">40</span>         }<span style="color: #0000FF; ">else</span> <span style="color: #0000FF; ">if</span>(ret > 0){<br /> <span style="color: #008080; ">41</span>             <span style="color: #0000FF; ">if</span>(<span style="color: #0000FF; ">event</span>.type != ENET_EVENT_TYPE_CONNECT){     <br /> <span style="color: #008080; ">42</span>                     fprintf(stderr, "enet_host_service event type %d is not connect", <span style="color: #0000FF; ">event</span>.type);<br /> <span style="color: #008080; ">43</span>                     <span style="color: #0000FF; ">goto</span> fail;<br /> <span style="color: #008080; ">44</span>             }<br /> <span style="color: #008080; ">45</span>             <span style="color: #0000FF; ">break</span>; <span style="color: #008000; ">//</span><span style="color: #008000; ">connect successfully</span><span style="color: #008000; "><br /> </span><span style="color: #008080; ">46</span> <span style="color: #008000; "></span><br /> <span style="color: #008080; ">47</span>         }<span style="color: #0000FF; ">else</span>{<br /> <span style="color: #008080; ">48</span>                 fprintf(stderr, "enet_host_service fail");        <br /> <span style="color: #008080; ">49</span>             <span style="color: #0000FF; ">goto</span> fail;<br /> <span style="color: #008080; ">50</span>         }<br /> <span style="color: #008080; ">51</span>     }<br /> <span style="color: #008080; ">52</span> <br /> <span style="color: #008080; ">53</span> #ifdef _DEBUG<br /> <span style="color: #008080; ">54</span>     <span style="color: #0000FF; ">char</span> local_ip[16], foreign_ip[16];<br /> <span style="color: #008080; ">55</span>     ENetAddress local_addr;<br /> <span style="color: #008080; ">56</span> <br /> <span style="color: #008080; ">57</span>     enet_socket_get_address((*host)->socket, &local_addr);<br /> <span style="color: #008080; ">58</span>     enet_address_get_host_ip(&local_addr, local_ip, <span style="color: #0000FF; ">sizeof</span>(local_ip));<br /><font color="#008080">59</font>     enet_address_get_host_ip(&(*peer)->address, foreign_ip, <span style="color: #0000FF; ">sizeof</span>(foreign_ip));<br /> <span style="color: #008080; ">60</span>     <br /> <span style="color: #008080; ">61</span>     printf("%s:%d connected to %s:%d", local_ip, loca_addr.port, foreign_ip, (*peer)->address.port);<br /> <span style="color: #008080; ">62</span> <span style="color: #0000FF; ">#endif</span><br /> <span style="color: #008080; ">63</span> <br /> <span style="color: #008080; ">64</span>     <span style="color: #0000FF; ">return</span> 0;<br /> <span style="color: #008080; ">65</span>     <br /> <span style="color: #008080; ">66</span> fail:<br /> <span style="color: #008080; ">67</span>     <span style="color: #0000FF; ">if</span>(*host) enet_host_destroy(*host); <br /> <span style="color: #008080; ">68</span>     <span style="color: #0000FF; ">return</span> -1;<br /><font color="#008080">69</font> }<br /> </div>    <br />     ◆ <strong style="font-size: 12pt;">断开q接</strong>Q若成功则返?Q超时返?Q出错返?1。先q行优雅关闭Q如p|再强制关?br /> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 14px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #008080; "> 1</span> <span style="color: #0000FF; ">int</span> <strong style="color: #993366; font-size: 12pt;">rudp_disconnect</strong>(ENetHost *host, ENetPeer *peer)<br /> <span style="color: #008080; "> 2</span> {<br /> <span style="color: #008080; "> 3</span>     <span style="color: #0000FF; ">int</span> ret;<br /> <span style="color: #008080; "> 4</span> <br /> <span style="color: #008080; "> 5</span> #ifdef _DEBUG<br /> <span style="color: #008080; "> 6</span>     <span style="color: #0000FF; ">char</span> local_ip[16], foreign_ip[16];<br /> <span style="color: #008080; "> 7</span>     ENetAddress local_addr;<br /> <span style="color: #008080; "> 8</span> <br /> <span style="color: #008080; "> 9</span>     enet_socket_get_address(host->socket, &local_addr);<br /> <span style="color: #008080; ">10</span>     enet_address_get_host_ip(&local_addr, local_ip, <span style="color: #0000FF; ">sizeof</span>(local_ip));<br /> <span style="color: #008080; ">11</span>     enet_address_get_host_ip(&peer->address, foreign_ip, <span style="color: #0000FF; ">sizeof</span>(foreign_ip));<br /> <span style="color: #008080; ">12</span>     <br /> <span style="color: #008080; ">13</span>     printf("%s:%d is disconnected from %s:%d", local_ip, local_addr.port, foreign_ip, peer->address.port);<br /> <span style="color: #008080; ">14</span> <span style="color: #0000FF; ">#endif</span><br /> <span style="color: #008080; ">15</span> <br /> <span style="color: #008080; ">16</span>     ENetEvent <span style="color: #0000FF; ">event</span>;<br /> <span style="color: #008080; ">17</span>     enet_peer_disconnect(peer, 0);<br /> <span style="color: #008080; ">18</span>         <br /> <span style="color: #008080; ">19</span>     <span style="color: #0000FF; ">while</span>((ret = enet_host_service(host, &<span style="color: #0000FF; ">event</span>, peer->roundTripTime)) > 0){<br /> <span style="color: #008080; ">20</span>         <span style="color: #0000FF; ">switch</span> (<span style="color: #0000FF; ">event</span>.type){<br /> <span style="color: #008080; ">21</span>         <span style="color: #0000FF; ">case</span> ENET_EVENT_TYPE_RECEIVE:<br /> <span style="color: #008080; ">22</span>             enet_packet_destroy (<span style="color: #0000FF; ">event</span>.packet);<br /> <span style="color: #008080; ">23</span>             <span style="color: #0000FF; ">break</span>;<br /> <span style="color: #008080; ">24</span>     <br /> <span style="color: #008080; ">25</span>         <span style="color: #0000FF; ">case</span> ENET_EVENT_TYPE_DISCONNECT:<br /> <span style="color: #008080; ">26</span>             ret = 0;<br /> <span style="color: #008080; ">27</span>             <span style="color: #0000FF; ">goto</span> disconn_ok;<br /> <span style="color: #008080; ">28</span>         }<br /> <span style="color: #008080; ">29</span>     }<br /> <span style="color: #008080; ">30</span> <br /> <span style="color: #008080; ">31</span>     ret = 0==ret ? 1 : -1;<br /> <span style="color: #008080; ">32</span> <br /> <span style="color: #008080; ">33</span>     fprintf(stderr, "enet_host_service with timeout %d %s", peer->roundTripTime, 1==ret?"timeout":"failure");<br /> <span style="color: #008080; ">34</span>     <br /> <span style="color: #008080; ">35</span>     enet_peer_reset(conn->peer);<br /> <span style="color: #008080; ">36</span> <br /> <span style="color: #008080; ">37</span> disconn_ok:    <br /> <span style="color: #008080; ">38</span>     enet_host_destroy(host);<br /> <span style="color: #008080; ">39</span>     <span style="color: #0000FF; ">return</span> ret;<br /> <span style="color: #008080; ">40</span> }</div> <br />     ◆ <strong style="font-size: 12pt;">发送数?/strong>Q若成功则返回已发送数据的长度Q否则返?1<br /> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 14px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #008080; "> 1</span> <span style="color: #0000FF; ">int</span> <strong style="color: #993366; font-size: 12pt;">rudp_sendmsg</strong>(ENetHost *host, ENetPeer *peer, ENetPacket *packet)<br /> <span style="color: #008080; "> 2</span> {<br /> <span style="color: #008080; "> 3</span>     <span style="color: #0000FF; ">int</span> ret;<br /> <span style="color: #008080; "> 4</span>     <br /> <span style="color: #008080; "> 5</span>     <span style="color: #0000FF; ">if</span>(enet_peer_send(peer, 0, packet)){<br /> <span style="color: #008080; "> 6</span>         fprintf(stderr, "enet send packet %lu bytes to peer fail", packet->dataLength);<br /> <span style="color: #008080; "> 7</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; "> 8</span>     }<br /> <span style="color: #008080; "> 9</span> <br /> <span style="color: #008080; ">10</span>     ret = enet_host_service(host, NULL, peer->roundTripTime);<br /> <span style="color: #008080; ">11</span>     <span style="color: #0000FF; ">if</span>(ret >= 0){<br /> <span style="color: #008080; ">12</span>         <span style="color: #0000FF; ">if</span>(peer->state == <span style="color: #ff00ff;">ENET_PEER_STATE_ZOMBIE</span>){<br /> <span style="color: #008080; ">13</span>             fprintf(stderr, "enet peer state is zombie");<br /> <span style="color: #008080; ">14</span>             <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">15</span>         }<br /> <span style="color: #008080; ">16</span>         <span style="color: #0000FF; ">return</span> packet->dataLength;<br /> <span style="color: #008080; ">17</span>         <br /> <span style="color: #008080; ">18</span>     }<span style="color: #0000FF; ">else</span>{<br /> <span style="color: #008080; ">19</span>         fprintf(stderr, "enet host service %u millsecond failure", peer->roundTripTime);<br /> <span style="color: #008080; ">20</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">21</span>     }<br /> <span style="color: #008080; ">22</span> }<br /> <span style="color: #008080; ">23</span> <br /> <span style="color: #008080; ">24</span> <span style="color: #0000FF; ">int</span> <strong style="color: #993366; font-size: 12pt;">rudp_send</strong>(ENetHost *host, ENetPeer *peer, <span style="color: #0000FF; ">const</span> <span style="color: #0000FF; ">void</span> *buf, size_t len)<br /> <span style="color: #008080; ">25</span> {<br /> <span style="color: #008080; ">26</span>     <span style="color: #0000FF; ">int</span> ret;<br /> <span style="color: #008080; ">27</span> <br /> <span style="color: #008080; ">28</span>     ENetPacket *packet = enet_packet_create(buf, len, <span style="color: #ff00ff;">ENET_PACKET_FLAG_RELIABLE</span>);<br /> <span style="color: #008080; ">29</span>     <span style="color: #0000FF; ">if</span>(NULL==packet){        <br /> <span style="color: #008080; ">30</span>         fprintf(stderr, "enet create packet %lu bytes fail", <span style="color: #0000FF; ">sizeof</span>(<span style="color: #0000FF; ">int</span>)+len);<br /> <span style="color: #008080; ">31</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">32</span>     }<br /> <span style="color: #008080; ">33</span> <br /> <span style="color: #008080; ">34</span>     <span style="color: #0000FF; ">return</span> <span style="color: #993366;">rudp_sendmsg</span>(host, peer, packet);<br /> <span style="color: #008080; ">35</span> }</div>    发送数据时需Ҏ对端状态判断是否断U,q且packet标志设ؓ可靠<br /> <br />    ◆ <strong style="font-size: 12pt;">接收数据</strong>Q若成功则返回已接收数据的长度,否则q回-1<br /> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 14px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #008080; "> 1</span> <span style="color: #0000FF; ">int</span> <strong style="font-size: 12pt; color: #993366;">rudp_recvmsg</strong>(ENetHost *host, ENetPeer *peer, ENetPacket **packet, unsigned <span style="color: #0000FF; ">int</span> timeout)<br /> <span style="color: #008080; "> 2</span> {<br /> <span style="color: #008080; "> 3</span>     <span style="color: #0000FF; ">int</span> ret;<br /> <span style="color: #008080; "> 4</span>     ENetEvent <span style="color: #0000FF; ">event</span>;<br /> <span style="color: #008080; "> 5</span> <br /> <span style="color: #008080; "> 6</span>     ret = enet_host_service(host, &<span style="color: #0000FF; ">event</span>, timeout);<br /> <span style="color: #008080; "> 7</span>     <span style="color: #0000FF; ">if</span>(ret > 0){<br /> <span style="color: #008080; "> 8</span>         <span style="color: #0000FF; ">if</span>(<span style="color: #0000FF; ">event</span>.peer != peer){<br /> <span style="color: #008080; "> 9</span>             fprintf(stderr, "enet receive peer is not matched");<br /> <span style="color: #008080; ">10</span>             <span style="color: #0000FF; ">goto</span> fail;<br /> <span style="color: #008080; ">11</span>         }<br /> <span style="color: #008080; ">12</span>         <span style="color: #0000FF; ">if</span>(<span style="color: #0000FF; ">event</span>.type != ENET_EVENT_TYPE_RECEIVE){<br /> <span style="color: #008080; ">13</span>             fprintf(stderr, "enet receive event type %d is not ENET_EVENT_TYPE_RECEIVE", <span style="color: #0000FF; ">event</span>.type);<br /> <span style="color: #008080; ">14</span>             <span style="color: #0000FF; ">goto</span> fail;<br /> <span style="color: #008080; ">15</span>         }<br /> <span style="color: #008080; ">16</span>         <br /> <span style="color: #008080; ">17</span>         *packet = <span style="color: #0000FF; ">event</span>.packet;<br /> <span style="color: #008080; ">18</span>         <span style="color: #0000FF; ">return</span> Q?packet)->dataLength;<br /> <span style="color: #008080; ">19</span>         <br /> <span style="color: #008080; ">20</span> fail:<br /> <span style="color: #008080; ">21</span>         enet_packet_destroy(<span style="color: #0000FF; ">event</span>.packet);<br /> <span style="color: #008080; ">22</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">23</span>         <br /> <span style="color: #008080; ">24</span>     }<span style="color: #0000FF; ">else</span> {<br /> <span style="color: #008080; ">25</span>         fprintf(stderr, "enet receive %u millsecond %s", timeout, ret?"failure":"timeout");<br /> <span style="color: #008080; ">26</span>         <span style="color: #0000FF; ">return</span> -1;        <br /> <span style="color: #008080; ">27</span>     }<br /> <span style="color: #008080; ">28</span> }<br /> <span style="color: #008080; ">29</span> <br /> <span style="color: #008080; ">30</span> <span style="color: #0000FF; ">int</span> <span style="color: #993366; font-size: 12pt;"><strong>rudp_recv</strong></span>(ENetHost *host, ENetPeer *peer, <span style="color: #0000FF; ">void</span> *buf, size_t maxlen, unsigned <span style="color: #0000FF; ">int</span> timeout) <br /> <span style="color: #008080; ">31</span> {<br /> <span style="color: #008080; ">32</span>     ENetPacket *packet;<br /> <span style="color: #008080; ">33</span> <br /> <span style="color: #008080; ">34</span>     <span style="color: #0000FF; ">if</span>(-1==<span style="color: #993366;">rudp_recvmsg</span>(host, peer, &packet, timeout))<br /> <span style="color: #008080; ">35</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">36</span> <br /> <span style="color: #008080; ">37</span>     <span style="color: #0000FF; ">if</span>(packet->dataLength > maxlen) {<br /> <span style="color: #008080; ">38</span>         fprintf(stderr, "enet packet data length %d is greater than maxlen %lu", packet->dataLength, maxlen);<br /> <span style="color: #008080; ">39</span>         <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">40</span>     }<br /> <span style="color: #008080; ">41</span> <br /> <span style="color: #008080; ">42</span>     memcpy(buf, packet->data, packet->dataLength);<br /> <span style="color: #008080; ">43</span>     enet_packet_destroy(packet);<br /> <span style="color: #008080; ">44</span>     <br /> <span style="color: #008080; ">45</span>     <span style="color: #0000FF; ">return</span> packet->dataLength;<br /> <span style="color: #008080; ">46</span> }</div>    <br />    ◆ <strong style="font-size: 12pt;">{待所有确?/strong>Q若成功q回0Q超时返?Q失败返?1<br /> <div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 14px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><span style="color: #008080; "> 1</span> <span style="color: #0000FF; ">int</span> <strong style="color: #993366; font-size: 12pt;">rudp_wait_allack</strong>(ENetHost *host, ENetPeer *peer, unsigned <span style="color: #0000FF; ">int</span> timeout)<br /> <span style="color: #008080; "> 2</span> {<br /> <span style="color: #008080; "> 3</span>     <span style="color: #0000FF; ">int</span> ret, cnt = 0;<br /> <span style="color: #008080; "> 4</span>     <br /> <span style="color: #008080; "> 5</span>     <span style="color: #0000FF; ">while</span>((ret = enet_host_service(host, NULL, 1)) >= 0){        <br /> <span style="color: #008080; "> 6</span>         <span style="color: #0000FF; ">if</span>(enet_peer_is_empty_sent_reliable_commands(peer, 0, <br /> <span style="color: #008080; "> 7</span>             ENET_PROTOCOL_COMMAND_SEND_RELIABLE|ENET_PROTOCOL_COMMAND_SEND_FRAGMENT))<br /> <span style="color: #008080; "> 8</span>             <span style="color: #0000FF; ">return</span> 0;<br /> <span style="color: #008080; "> 9</span> <br /> <span style="color: #008080; ">10</span>         <span style="color: #0000FF; ">if</span>(peer->state == <span style="color: #ff00ff;">ENET_PEER_STATE_ZOMBIE</span>){<br /> <span style="color: #008080; ">11</span>             fprintf(stderr, "enet peer state is zombie");<br /> <span style="color: #008080; ">12</span>             <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">13</span>         }<br /> <span style="color: #008080; ">14</span>     <br /> <span style="color: #008080; ">15</span>         <span style="color: #0000FF; ">if</span>(0==ret && ++cnt>=timeout){<br /> <span style="color: #008080; ">16</span>             <span style="color: #0000FF; ">return</span> 1;<br /> <span style="color: #008080; ">17</span>         }<br /> <span style="color: #008080; ">18</span>     }<br /> <span style="color: #008080; ">19</span>     <br /> <span style="color: #008080; ">20</span>     fprintf(stderr, "enet host service fail");<br /> <span style="color: #008080; ">21</span>     <span style="color: #0000FF; ">return</span> -1;<br /> <span style="color: #008080; ">22</span> }</div>     {待已发送数据的所有确认时Q需Ҏ对端状态判断是否断U?br /> <br /> <strong style="font-size: 13pt;">CZ程</strong>   <br />    左边为客LQ压~ƈ传输文gQ右边ؓ服务端,接收q解压存储文件?br />    <br /><img src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/rudp_trans_file_flow.png" alt="" /><br />   客户端【读文g块ƈ压羃】这个环节,需要显式创建可靠packetQƈ压~后的块拯到其?img src ="http://m.shnenglu.com/qinqing1984/aggbug/217279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2020-05-04 19:08 <a href="http://m.shnenglu.com/qinqing1984/archive/2020/05/04/217279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ȝ|络路由走向诊断Ҏhttp://m.shnenglu.com/qinqing1984/archive/2017/12/29/215452.html春秋十二?/dc:creator>春秋十二?/author>Fri, 29 Dec 2017 09:24:00 GMThttp://m.shnenglu.com/qinqing1984/archive/2017/12/29/215452.htmlhttp://m.shnenglu.com/qinqing1984/comments/215452.htmlhttp://m.shnenglu.com/qinqing1984/archive/2017/12/29/215452.html#Feedback0http://m.shnenglu.com/qinqing1984/comments/commentRss/215452.htmlhttp://m.shnenglu.com/qinqing1984/services/trackbacks/215452.html׃traceroute只能诊断UDP通信的包路由Q不能确定TCP通信的实际\由(可能变换Q,因此~写了本文。ؓ方便描述Q下面的IP、MAC和端口均为示例,实际诊断中可更换为具体的?/div>

1. 如何判断客户端到服务器的TCP包,是否l过了网?/strong>
     在客L执行 tcpdump -i eno16777728 ether dst b0:b9:8a:69:65:3e and host 192.168.0.26 and tcp port 80  抓取l过|关且往q服务器的TCP端口?0的包
     eno16777728 接口名称Qether 以太|链路,dst 目标Qsrc表示源)Qb0:b9:8a:69:65:3e |关MAC地址Q?92.168.0.26 服务器IP地址Q?0 监听端口

     输出l果分析
       ● 有输出,则表C经q了|关
       ● 有部分输TCP通信q在q行Q则表示先前的包l过了网养I后来路由表项~存被重定向更新Q没l过|关?/div>
       ● 不断输出Q则表示一直经q网?/div>

2. 如何判断路由表项~存被重定向更新
     在客L执行 tcpdump -i eno16777728 src 192.168.1.1 and dst 192.168.1.45 and icmp  抓取来自|关和到辑֮L的所有icmp?/div>
     192.168.1.1 |关IPQ?92.168.1.45 客户端(出口QIP

     输出l果分析
       ● 没有输出Q则表示没有收到rerdirect包,路由表项~存不变
       ● 有输出类?span style="color: #ff0000;">ICMP redirect 192.168.0.26 to host 192.168.0.26Q前面一个IP表示到达服务器的直接路由IPQ后一个表C服务器IPQ?/div>
       ● 则表C收CICMP重定向包Q内怼更新路由表项及缓存网关ؓ192.168.0.26Q下ơ通信时就直接发往192.168.0.26?/div>

3. 如何控制接收ICMP重定?/strong>
      ● echo 0 | tee /proc/sys/net/ipv4/conf/*/accept_redirects    止所有网卡接Ӟ可避免\p缓存被修改
      ● echo 1 | tee /proc/sys/net/ipv4/conf/*/accept_redirects    启用所有网卡接收ICMP重定向消?/div>

4. 查看、刷新\p缓?/strong>
      ● ip route get 192.168.0.26    可以从输Z看到通住目标IP的实际\?/div>
      ● ip route flush cache             清空路由表项~存Q下ơ通信时内怼查main表(卛_令route输出的表Q以定路由


]]>深入理解SSL/TLS技术内q?/title><link>http://m.shnenglu.com/qinqing1984/archive/2016/12/15/214491.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Thu, 15 Dec 2016 09:16:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2016/12/15/214491.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/214491.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2016/12/15/214491.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/214491.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/214491.html</trackback:ping><description><![CDATA[<strong style="font-size: 12pt">前言</strong><br />    q期有机会,深入了SSL/TLS协议原理与细节,q分析了相关密码学内容,心得颇多Q历l半月,l于写成了这份文档?br />    本h水^有限,错误隑օQ欢q指正,不胜感激?br /> <br /> <strong style="font-size: 12pt">目录</strong><br />          <img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/deep-ssl-tls-catalogue.png" /><strong><br /> <br /> </strong><strong style="font-size: 12pt">部分章节预览</strong><br /> <strong>   W??/strong><br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/ssl-tls-protocol-stack.png" /></div> <br /> <br />    <strong>W?章第4?/strong><br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/ssl-tls-block-cipher.png" /></div> <br /> <br />    <strong>W?1章第3?br /> </strong> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/ssl-tls-freak-attack.png" /></div> <br /> <strong style="font-size: 12pt">全文</strong><br />    下蝲地址Q?a href="/Files/qinqing1984/深入理解SSL-TLS技术内q?zip">深入理解SSL/TLS技术内q?/a> <img src ="http://m.shnenglu.com/qinqing1984/aggbug/214491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2016-12-15 17:16 <a href="http://m.shnenglu.com/qinqing1984/archive/2016/12/15/214491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一U拦截Linux原始套接字IO的方?/title><link>http://m.shnenglu.com/qinqing1984/archive/2016/07/14/213936.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Thu, 14 Jul 2016 02:27:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2016/07/14/213936.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/213936.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2016/07/14/213936.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/213936.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/213936.html</trackback:ping><description><![CDATA[<strong style="font-size: 14pt;">描述</strong><br />    原始套接字具有广泛的用途,特别是用于自定义协议Q标准协议TCP、UDP和ICMP{外Q的数据收发。在Linux下拦截套接字IO的一般方法是拦截对应的套接字pȝ调用Q对于发送ؓsendmsg和sendtoQ对于接收ؓrecvmsg和recvfrom。这U方法虽然也能拦截原始套接字IOQ但要先判断套接字的cdQ如果ؓSOCK_RAWQ原始套接字cdQ,那么q行拦截处理Q这样一来由于每ơIO都要判断套接字类型,性能比较低了。因此ؓ了直接针对原始套接字来拦截,提高性能Q发明了本方法?br />    本方法可用于防火墙或L防护pȝ中,丢弃接收和发送的d或病毒数据包?br /> <br /> <strong style="font-size: 14pt"> 特点</strong><br />    q行在内核态,直接拦截所有进E的原始套接字IOQ支持IPv4和IPv6?br /> <br /> <p><strong style="font-size: 14pt"> </strong></p> <hr /> <strong style="font-size: 14pt"> 实现</strong><br />    <strong style="font-size: 12pt">原理</strong><br />       在Linux内核|络子系l中Qstruct proto_opsl构提供了协议无关的套接字层到协议相关的传输层的转接Q而IPv4协议族中内置的inet_sockraw_ops为它的一个实例,对应着原始套接字。因此先扑ֈinet_sockraw_opsQ再替换它的成员函数指针recvmsg和sendmsgQ就可以实现拦截了。下面以IPv4ZQIPv6同理Q,说明几个程?br /> <br />    <strong style="font-size: 12pt">搜烦inet_sockraw_ops</strong><br />       该流E在挂钩IO前进行。由于inet_sockraw_ops为Linux内核未导出的内部W号Q因此需要通过特别的方法找到它Q该特别的方法基于这L一个事实:<br />       <span style="font-size: 1pt">◆</span> 所有原始套接字接口均存攑֜以SOCK_RAW为烦引的双向循环链表中,而inet_sockraw_ops在该链表的末尾?br />       <span style="font-size: 1pt">◆</span> 内核提供了注册套接字接口的API inet_register_protoswQ对于原始套接字cdQ该API输入的套接字接口插入到链表头后面?br />       法如下<br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/search_inet_sockraw_ops.png" width="198" height="420" /></div>       <br />       注册p前或注销p后,链表如下<br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/reg_before_rawsock_list.png" width="450" height="83" /></div>       注册p后,链表如下<br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/reg_after_rawsock_list.png" width="673" height="82" /></div> <br /> <strong style="font-size: 12pt">   挂钩IO</strong><br />       该流E在内核模块启动时进行?br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/hook_rawsock_io.png" width="196" height="458" /></div> <br />    <strong style="font-size: 12pt">協RIO</strong><br />       该流E在内核模块退出时q行?br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/unhook_rawsock_io.png" width="191" height="460" /></div> <br /> <strong style="font-size: 14pt"> <hr /> q行部v</strong><br />    该方法实现在Linux内核模块中,Z防止其它内核模块可能也注册了原始套接字接口,因此需要在操作pȝ启动时优先加载?nbsp; <img src ="http://m.shnenglu.com/qinqing1984/aggbug/213936.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2016-07-14 10:27 <a href="http://m.shnenglu.com/qinqing1984/archive/2016/07/14/213936.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一UP2P代理中TCPq接调度的方?/title><link>http://m.shnenglu.com/qinqing1984/archive/2016/07/12/213924.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Tue, 12 Jul 2016 08:59:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2016/07/12/213924.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/213924.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2016/07/12/213924.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/213924.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/213924.html</trackback:ping><description><![CDATA[<strong style="font-size: 14pt;">描述</strong><br />    在P2P应用pȝ中,当需要与处于不同U网的对方可靠通信Ӟ先尝试TCP打洞IK,若穿透失败,再通过处于公网上的代理服务器(下文UproxyQ{发与Ҏ通信Q如下图所C?nbsp;  <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/p2p_comm_arch.png" width="557" height="311" /></div>    l端A先连接ƈ发消息msg1到proxyQ连接ؓc1Q;proxy再发消息msg2lP2P服务器,P2P服务器收到消息后通过已有的连接发消息msg3l终端BQB收到msg3后,q接q发消息msg4到proxyQ连接ؓc2Q。这4个消息格式由应用层协议决定,但必遵守的规范如下Q?br />    <span style="font-size: 6pt">◆</span> msg1臛_包含B的设备ID?br />    <span style="font-size: 6pt">◆</span> msg2臛_包含B的设备ID和c1的连接ID?br />    <span style="font-size: 6pt">◆</span> msg3臛_包含c1的连接ID和连接代理指C?br />    <span style="font-size: 6pt">◆</span> msg4臛_包含B的设备ID和c1的连接ID?br />    proxy为多U程架构Q当接受到若q连接时Q如果数据相互{发的两个q接Q比如上图中的c1和c2Q不在同一U程Q由于一个连接写数据到另一q接的发送队列,而另一q接从发送队列读数据以发送,那么p对另一q接的发送队列(或缓冲区Q加锁,q样一来由于频J的|络IO而频J地加解锁,降低了{发效率,因此Z解决q一问题Q就需要调度TCPq接到同一U程?<br /> <br /> <hr /> <strong style="font-size: 14pt">特点</strong><br />    本方法能数据{发的两边q接攑֜同一U程Q从而避免了数据转发时的加锁Q由于是一对一的连接匹配,因此也做C每个U程中连接数的均衡?br /> <br /> <hr /> <strong style="font-size: 14pt">实现</strong><br />    <strong style="font-size: 12pt">工作原理</strong><br />       proxy的主U程负责l定知名端口q监听连接,工作U程负责数据转发。当接受C个连接时Q按轮{法调度它到某个工作线E,在那个线E内接收分析应用层协议数据,以识别连接类型,卛_断连接是来自数据h方还是数据响应方Qؓl一描述Q这里把前者特UCؓ客户q接Q后者ؓ服务q接Q连接所在的U程为宿ȝE。如果是客户q接Q那么先通知P2P服务器请求对应的客户端来q接代理Qƈ{待匚wQ如果是服务q接Q那么就d配客戯接,在匹配过E中Q如果服务连接和客户q接不在同一U程内,那么׃调度到客戯接的宿主U程Q匹配成功后Q就开始{发数据?br />       Z加快查找Q分2个hash表存放连接,客户q接攑֜客户q接hash表中Q以q接ID为键|服务q接攑֜服务q接hash表中Q以讑֤ID为键倹{?br /> <br />    <strong style="font-size: 12pt">TCPq接调度<br /> </strong>      包括新连接的轮{、识别连接类型、匹配客戯?、匹配客戯?和关闭连接共5个流E,如下一一所q?br />       <strong>新连接的轮{</strong><br />          该流E工作在ȝE,如下图所C?br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/new_conn_round_robin.png" /></div>       索引i初始?Q对于新来的q接Q由于还不明连接类型,所以先攑օ客户q接表中?br /> <br />       <strong>识别q接cd</strong><br />          该流E工作在工作U程Q当接受C个连接时开始执行,如下图所C? <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/recognition_conn.png" /></div>       当连接类型ؓ服务q接Ӟ从客戯接表转移到服务连接表?br /> <br />       <strong>匚w客户q接1</strong><br />          该流E工作在工作U程Q当接受C个服务连接时开始执行,如下图所C?br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/match_client_conn_1.png" /></div> <br />       <strong>匚w客户q接2</strong><br />          该流E工作在工作U程Q当服务q接Ud客户q接的宿ȝE时开始执行,如下图所C?br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/match_client_conn_2.png" /></div>       q里的流E和匚w客户q接程1有些cMQ看h好像做了重复的判断操作,但这是必要的Q因为在服务q接转移到另一U程q个瞬间内,客户q接有可能断开了,也有可能断开后又来了一个相同连接ID的其它客戯接,所以要重新d戯接表查找一ơ,然后q行4个分支判断?nbsp;<br />    <br />       <strong>关闭q接</strong><br />          该流E工作在工作U程内,当连接断开或空闲时执行。当一边读数据出错Ӟ不能马上关闭另一边连接,得在另一边缓冲区数据发送完后才能关闭;当一边连接写数据出错Ӟ可以马上关闭另一边连接,如下图所C?br /> <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/p2p_close_conn.png" /></div><img src ="http://m.shnenglu.com/qinqing1984/aggbug/213924.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2016-07-12 16:59 <a href="http://m.shnenglu.com/qinqing1984/archive/2016/07/12/213924.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCP分组丢失时的状态变q?/title><link>http://m.shnenglu.com/qinqing1984/archive/2015/10/05/211950.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Sun, 04 Oct 2015 16:44:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2015/10/05/211950.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/211950.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2015/10/05/211950.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/211950.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/211950.html</trackback:ping><description><![CDATA[   本文ҎRFC793协议规范和BSD 4.4的实玎ͼȝ?span style="color: red;">TCP分组丢失?/span>的状态变q,如下图所C:实线头表示客户端的状态变q,U段虚线头表示服务端的状态变q,圆点虚线头表示客户端或服务端的状态变q;黑色文字表示正常时的行ؓQ红色文字表C分l丢失时的行为? <div align="center"><img border="0" alt="" src="http://m.shnenglu.com/images/cppblog_com/qinqing1984/tcp_lose_packet_state.PNG" /></div> <br />    q里假设重传时分l依然会丢失Q当在不同状态(CLOSED除外Q分l丢失后Q最l会关闭套接字而回到CLOSED状态。下面逐个分析各状态时的情景?br /> <br /> <strong>SYN_SENT</strong><br />    q接阶段W?ơ握手,客户端发送的SYN分组丢失Q因此超时收不到服务端的SYN+ACK而重传SYNQ尝试几ơ后攑ּQ关闭套接字?br /> <br /> <strong>SYN_RCVD</strong><br />    1Q连接阶D늬2ơ握手,服务端响应的SYN+ACK分组丢失Q因此超时收不到客户端的ACK而重传SYN+ACKQ尝试几ơ后攑ּQ发送RSTq关闭套接字?br />    2Q连接阶D늬3ơ握手,客户端发送的ACK分组丢失Q因此服务端时收不到ACK而重传SYN+ACKQ尝试几ơ后攑ּQ发送RSTq关闭套接字?br />    3Q同时打开W?ơ握手,本端响应的SYN+ACK分组丢失Q因此对端超时收不到SYN+ACK而重传SYN、尝试几ơ后攑ּ、发送RSTq关闭套接字Q而此时本端收到RST?br /> <br /> <strong>ESTABLISHED</strong><br />    1Q连接阶D늬3ơ握手,客户端发送ACK分组后,虽然丢失但会q入该状态(因ؓACK不需要确认)Q但此时服务端还处于SYN_RCVD状态,因ؓ时收不到客L的ACK而重传SYN+ACK、尝试几ơ后攑ּ、发送RSTq关闭套接字Q而此时客L收到RST?br />    2Q数据传输阶D,本端发送的Data分组丢失Q因此超时收不到Ҏ据的认而重传、尝试几ơ后攑ּ、发送RSTq关闭套接字Q而此时对端收到RST?br /> <br /> <strong>FIN_WAIT_1</strong><br />    1Q关闭阶D늬1ơ握手,客户端发送的FIN分组丢失Q因此超时收不到服务端的ACK而重传FINQ尝试几ơ后攑ּQ发送RSTq关闭套接字?br />    2Q关闭阶D늬2ơ握手,服务端响应的ACK分组丢失Q因此客L时收不到ACK而重传FINQ尝试几ơ后攑ּQ发送RSTq关闭套接字?br />  <br /> <strong>FIN_WAIT_2</strong><br />    关闭阶段W?ơ握手,服务端发送的FIN分组丢失Q因此超时收不到客户端的ACK而重传FIN、尝试几ơ后攑ּ、发送RSTq关闭套接字Q而此时客L收到RST?br />  <br /> <strong>CLOSING</strong><br />    同时关闭W?ơ握手,本端发送的ACK分组丢失Q导致对端超时收不到ACK而重传FIN、尝试几ơ后攑ּ、发送RSTq关闭套接字Q而此时本端收到RST?<br /> <br /> <strong>TIME_WAIT</strong><br />    关闭阶段W?ơ握手,客户端响应的ACK分组丢失Q导致服务端时收不到ACK而重传FIN、尝试几ơ后攑ּ、发送RSTq关闭套接字Q而此时客L收到RST?<br /> <br /> <strong>CLOSE_WAIT</strong><br />    关闭阶段W?ơ握手,服务端响应的ACK分组丢失Q导致客L时收不到ACK而重传FIN、尝试几ơ后攑ּ、发送RSTq关闭套接字Q而此时服务端收到RST?br /> <br /> <strong>LAST_ACK</strong><br />    关闭阶段W?ơ握手,服务端发送的FIN分组丢失Q导致超时收不到客户端的ACK而重传FIN、尝试几ơ后攑ּ、发送RSTq关闭套接字? <img src ="http://m.shnenglu.com/qinqing1984/aggbug/211950.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2015-10-05 00:44 <a href="http://m.shnenglu.com/qinqing1984/archive/2015/10/05/211950.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux ICMP消息的生与转换http://m.shnenglu.com/qinqing1984/archive/2015/05/18/210684.html春秋十二?/dc:creator>春秋十二?/author>Mon, 18 May 2015 11:52:00 GMThttp://m.shnenglu.com/qinqing1984/archive/2015/05/18/210684.htmlhttp://m.shnenglu.com/qinqing1984/comments/210684.htmlhttp://m.shnenglu.com/qinqing1984/archive/2015/05/18/210684.html#Feedback0http://m.shnenglu.com/qinqing1984/comments/commentRss/210684.htmlhttp://m.shnenglu.com/qinqing1984/services/trackbacks/210684.htmlicmp_err_convert数组?span style="color: red">icmp_send函数Q供其它|络子系l用。在其它|络子系l中Q当到错误Ӟ调用icmp_send产生q发送相应的ICMP差错消息到源LQ当源主机收到ICMP不可辑ַ错消息,传递到原始套接字和传输层,而它们用icmp_err_convert把对应的消息代码转换成套接字层比较容易理解的错误代码。在内核I间中可发送的ICMP消息包括查询应答和差错报文,下面ȝ了生这两类消息的网l子pȝQ及函数Q与错误转换?br />

应答消息
   应答消息由ICMP模块的内部函数icmp_reply而非icmp_send发送。根?a target="_blank">RFC1122 3.2.2.9规范Q?nbsp;除非一个主Z为地址掩码代理Q否则不能发送回复,q对应ICMP的icmp_address实现为空Q因此上表没有列出地址掩码应答(内核W号为ICMP_ADDRESSREPLYQ?br />
差错消息
   差错消息׃间\由器或目的主Z生,当数据报不能成功提交l目的主机时。从上表可见Q在IP层的接收、本地处理、{发和输出各过E中Q都可能产生差错消息Q在传输层如果对应的端口没有打开Q那么UDP会生ICMP端口不可辑ַ错,?span style="color: red;">TCP则会使用自己的差错处理机制发送一个RST复位包,q也是上表没有列出TCP子系l的原因。对于重定向差错Q由ICMP模块的icmp_redirect调用ip_rt_redirect更新路由Q其它差错则由icmp_unreach处理?br />

错误转换
   W?列ؓicmp_err_convert数组索引Q第4列也是调用socket API出错时返回的errnoQ最?列ؓicmp_err_convert中的fatal成员取|0表示非致命错误,1表示致命错误Q需要报告给用户q程。错误{换会被RAW的raw_err、TCP的tcp_v4_err和UDP的udp_err用到Q对于ICMP_DEST_UNREACHcd的差错,使用上表转换QICMP_SOURCE_QUENCHcd的忽略不处理QICMP_PARAMETERPROBcd的{换成EPROTOQ协议错误)QICMP_TIME_EXCEEDEDcd的{换成EHOSTUNREACH?br />    在这要注意,从ICMP_PORT_UNREACH到ECONNREFUSED的{换,不适用于TCPQ原因已?a href="#icmp_error_msg">上节说明Q而对于UDP?span style="color: red">未连?/span>套接字,如果L在线而端口没打开Q调用sendto得不到ECONNREFUSED错误Q但recvfrom会阻塞,q是因ؓ虽然内核收到了ICMP差错Q但没上报给应用q程。尽如此,如果惛_到ECONNREFUSED错误Q那么可以写个ICMP守护q程Q应用进E先把它的套接字描述W通过unix域套接口传递到ICMP守护q程Q而守护进E用raw socket来接收ICMP差错Q再发给应用q程?span style="color: red">


发送限?/strong>
   不论一般差错消息还是重定向差错消息Q发送限速针对的都是特定目标L?br />    一般限?/strong>
   在用icmp_send发送差错消息(PMTU消息除外Q时Qؓ减少|络拥塞而限制了发送的速率Q限速由xrlim_allow函数实现Q定义在ipv4/icmp.c中?br />
 1#define XRLIM_BURST_FACTOR 6
 2int xrlim_allow(struct dst_entry *dst, int timeout)
 3{
 4    unsigned long now, token = dst->rate_tokens;
 5    int rc = 0;
 6
 7    now = jiffies;
 8    token += now - dst->rate_last;
 9    dst->rate_last = now;
10    if (token > XRLIM_BURST_FACTOR * timeout)
11        token = XRLIM_BURST_FACTOR * timeout;
12    if (token >= timeout) {
13        token -= timeout;
14        rc = 1;
15    }

16    dst->rate_tokens = token;
17    return rc;
18}
   dst为目标\q存,timeout为允许发送的时Q单位ؓjiffiesQ,dst->rate_tokens记录令牌的个敎ͼ当o牌个C于timeoutӞ则减timeoutq允许发送一个消息;反之则不能发送,需{到令牌个数累积到大于timeout时才能发送,但是不能无限大,否则׃D在一个可能很短的timeout内,发送远多于6个的消息Q引起ICMP风暴Q所以这里限制了令牌的最大gؓXRLIM_BURST_FACTOR*timeout?倍的时Q也是说在一个timeout内,最多能发?个差错消息?nbsp;
  
   重定向限?/strong>
   路由子系l用ip_rt_send_redirect来发送重定向消息Q定义在ipv4/route.c中,该函数内部调用icmp_send实现Q在它的限速基上,使用指数回退法控制发送速率?br />
 1void ip_rt_send_redirect(struct sk_buff *skb)
 2{
 3    struct rtable *rt = skb_rtable(skb);
 4    
   
 5
 6    /* No redirected packets during ip_rt_redirect_silence;
 7     * reset the algorithm.
 8     */

 9    if (time_after(jiffies, rt->u.dst.rate_last + ip_rt_redirect_silence))
10        rt->u.dst.rate_tokens = 0;
11
12    /* Too many ignored redirects; do not send anything
13     * set u.dst.rate_last to the last seen redirected packet.
14     */

15    if (rt->u.dst.rate_tokens >= ip_rt_redirect_number{
16        rt->u.dst.rate_last = jiffies;
17        return;
18    }

19
20    /* Check for load limit; set rate_last to the latest sent
21     * redirect.
22     */

23    if (rt->u.dst.rate_tokens == 0 || time_after(jiffies, (rt->u.dst.rate_last (ip_rt_redirect_load << rt->u.dst.rate_tokens)))) {
24        icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
25        rt->u.dst.rate_last = jiffies;
26        ++rt->u.dst.rate_tokens;
27        
28    }

29}
   重定向差错用ip_rt_redirect_silenceQ默认ؓ(HZ/50)<<10Q、ip_rt_redirect_numberQ默认ؓ9Q和ip_rt_redirect_loadQ默认ؓHZ/50Q?个量来控制发送的速率Qrt->u.dst.rate_last记录上次发送的旉Qrt->u.dst.rate_tokens累计发送LQ最大gؓip_rt_redirect_numberQ当两次发送的旉间隔过ip_rt_redirect_silence或ip_rt_redirect_load<<rt->u.dst.rate_tokensQƈ且发送L不超qip_rt_redirect_numberӞ才允许发送一个,q样一来,在ip_rt_redirect_silence间隔内,每次发送的时?的指数增长,辑ֈ了变减速发送的效果Q直到L辑ֈip_rt_redirect_number时停止发送,q是因ؓ源主机可能忽略了重定向消息所以停止发送;当ip_rt_redirect_silence旉q后Q又允许发送了Q这是因为源L没有更新路由所以又需要发送?img src ="http://m.shnenglu.com/qinqing1984/aggbug/210684.html" width = "1" height = "1" />

]]>
Linux套接字与虚拟文gpȝQ?Q:操作和销?/title><link>http://m.shnenglu.com/qinqing1984/archive/2015/05/03/210522.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Sun, 03 May 2015 08:55:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2015/05/03/210522.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/210522.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2015/05/03/210522.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/210522.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/210522.html</trackback:ping><description><![CDATA[     摘要:    接上初始化与创建,本篇阐述Socket操作和销毁两部分的实现? Socket操作    pȝ调用read(v)、write(v)是用L间读写socket的一U方法,Z弄清楚它们是怎么通过VFS请求{发到特定协议的实玎ͼ下面以readZQwrite同理Q,q假定文件描q符对应的是IPv4 TCPcd的socket...  <a href='http://m.shnenglu.com/qinqing1984/archive/2015/05/03/210522.html'>阅读全文</a><img src ="http://m.shnenglu.com/qinqing1984/aggbug/210522.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2015-05-03 16:55 <a href="http://m.shnenglu.com/qinqing1984/archive/2015/05/03/210522.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux套接字与虚拟文gpȝQ?Q:初始化和创徏http://m.shnenglu.com/qinqing1984/archive/2015/05/03/210521.html春秋十二?/dc:creator>春秋十二?/author>Sun, 03 May 2015 08:31:00 GMThttp://m.shnenglu.com/qinqing1984/archive/2015/05/03/210521.htmlhttp://m.shnenglu.com/qinqing1984/comments/210521.htmlhttp://m.shnenglu.com/qinqing1984/archive/2015/05/03/210521.html#Feedback0http://m.shnenglu.com/qinqing1984/comments/commentRss/210521.htmlhttp://m.shnenglu.com/qinqing1984/services/trackbacks/210521.html阅读全文

]]>
HTTP URI~解?/title><link>http://m.shnenglu.com/qinqing1984/archive/2015/02/10/191972.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Tue, 10 Feb 2015 10:40:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2015/02/10/191972.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/191972.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2015/02/10/191972.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/191972.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/191972.html</trackback:ping><description><![CDATA[     摘要: 字符集合     依据RFC3986 2规范QHTTP URI中允许出现的US-ASCII字符的子集,可以分成保留、未保留及{义这几类Q每cȝ全部字符列表如下       ● 保留:  : / ? # [ ] @ ! $ & '( ) * + ,; =?8个,一?..  <a href='http://m.shnenglu.com/qinqing1984/archive/2015/02/10/191972.html'>阅读全文</a><img src ="http://m.shnenglu.com/qinqing1984/aggbug/191972.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2015-02-10 18:40 <a href="http://m.shnenglu.com/qinqing1984/archive/2015/02/10/191972.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZOpenSSL实现的安全连?/title><link>http://m.shnenglu.com/qinqing1984/archive/2014/04/11/206536.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Fri, 11 Apr 2014 09:26:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2014/04/11/206536.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/206536.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2014/04/11/206536.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/206536.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/206536.html</trackback:ping><description><![CDATA[     摘要:    Web服务器ؓ了支持https讉KQ通常会用第三方库openssl实现Q而且Z高性能采用异步事g驱动模型Q因此连接套接字被设为非dcdQ本文在nginx ssl模块的基上,化提取它的核心框Ӟ使用面向对象的方式描qͼ从握手、读写和关闭3个方面进行了分析Q由于这3个操作都是异步的Q因此操作失败后要调用SSL_get_error来获取错误码Q有如下4U情c?&n...  <a href='http://m.shnenglu.com/qinqing1984/archive/2014/04/11/206536.html'>阅读全文</a><img src ="http://m.shnenglu.com/qinqing1984/aggbug/206536.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2014-04-11 17:26 <a href="http://m.shnenglu.com/qinqing1984/archive/2014/04/11/206536.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCP/IP FAQ Q?Q:插口层和应用?/title><link>http://m.shnenglu.com/qinqing1984/archive/2013/09/03/202876.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Tue, 03 Sep 2013 07:52:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2013/09/03/202876.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/202876.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2013/09/03/202876.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/202876.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/202876.html</trackback:ping><description><![CDATA[   l上?a href="http://m.shnenglu.com/qinqing1984/archive/2013/08/25/202734.html" target="_blank">TCP/IP FAQQ?Q?/a>Q本涵盖了域和协议、IP~址、插口、原始IP、unix域方面的问题与解{?br /> <span style="color: #ff6600; font-size: 12pt"><br /> 【Domain & Protocol?/span><br /> <span style="color: #008000"><strong>1. 什么是域,它和协议有什么关p?</strong></span><br />    域可以理解ؓ一U容U_议的I间Q它的存在便于了协议的分c;域和协议是集合与元素的关p,一个域中的每个协议使用同类地址Qƈ且每U地址只被一个域使用Q一个域能由协议族或地址族常量唯一标识?br /> <span style="color: #008000"><strong>2. TCP/IP中有哪些域及其协议?</strong></span><br />    internet、iso、route、ccitt、imp、network systems和unixQ其中internet域含有ip,icmp,igmp,tcp和udp五种协议Qunix域用于ipc通信?br /> <span style="color: #008000"><strong>3. 哪些地方会用到域Q?/strong></span><br />    一个网l层协议必须分用输入数据报,q交l相应的传输层协议,׃域包含了协议族,因此必须从对应的域中扑ֈ合适的协议d理。例如IP对应的域为internetQ这个域对应的协议族为inetswQ当收到IP数据报时Q就从inetsw中找到对应的传输层协议去输入处理?br /> <br /> <span style="color: #ff6600; font-size: 12pt">【IP Addressing?/span><br /> <span style="color: #008000"><strong>1. IP地址有哪几类Q?/strong></span><br />    分ؓ5c,A、B和Ccȝ于单播;Dcȝ于多播;Ecȝ于实验?br /> <span style="color: #008000"><strong>2. sockaddr和sockaddr_in有什么区别联p?</strong></span><br />    sockaddr是一U通用的用于接口编址信息的结构,它将g与协议的地址l节相对于接口层隐藏hQ成员依ơؓsa_len、sa_family和sa_dataQ而sockaddr_in成员依次为sin_len、sin_family、sin_port、sin_addr和sin_zero。它们的前两个成员其实是一LQ只是命名不同,而sockaddr_in中的sin_port标识传输层的端口Qsin_addr标识IP层的地址Q所以它是Internet协议的专用接口编址l构Qsin_zero仅ؓ填充用,因ؓsockaddr_in长度不应于sockaddr?br /> <span style="color: #008000"><strong>3. 插口~址l构允许的最大长度是多少Q?/strong></span><br />    sockaddr最后一个成员是可扩展的Q这是C语言的通用技术,因ؓ其第一个成员ؓu_charcdQ所以最大长度是255?br /> <span style="color: #008000"><strong>4. 一个接口可以配|多个IP地址Q是怎么实现的?</strong></span><br />    ifaddr表示通用的接口地址Qifnet表示接口Q它有个cd为ifaddr*的if_addrlist成员Q表C当前接口上的地址链表。in_ifaddr表示Internet协议专用的接口地址Q而IP属于Internet协议Q因此用in_ifaddr表示Q所有的IP地址l成一个类型ؓin_ifaddr*的链表。当增加一个IP地址Ӟ需要插入这两个链表中;当删除一个IP地址Ӟ需要从它们当中U除?br /> <span style="color: #008000"><strong>5. Z么配|IPL地址和网l掩码可以是独立的?</strong></span><br />    因ؓ它们使用不同的命令实玎ͼ前者用SIOCSIFADDRQ后者用SIOCSIFNETMASK。当配置IPL地址Ӟ如果没有指明|络掩码Q那么网l掩码被讄成默认的?br /> <span style="color: #008000"><strong>6. Z么访问IP接口地址使用的是UDP插口而不是原始IP插口Q?/strong></span><br />    只有用户用程才能创徏原始IP插口Q而通过UDP插口QQ何用戯E都能查看接口配|?br /> <br /> <span style="color: #ff6600; font-size: 12pt">【Socket?/span><br /> <span style="color: #008000"><strong>1. Z么会存在插口层?</strong></span><br />    从概念上Ԍtcp/ip协议栈划分ؓ链\、网l、传输和应用4层;但从实现上讲Q在应用层和其下层中_引入了一个插口层Q作E和内核通信的桥梁,主要功能是将q程发送的与协议有关的h映射C生插口时指定的与协议有关的实玎ͼ从而屏蔽了不同协议处理的细节?br /> <span style="color: #008000"><strong>2. Z么服务器q程L要调用bindQ客戯E能调用它吗Q?/strong></span><br />    bind一个本地地址同一个插口相兌Q客戯E需要同一个已知地址建立q接或发送数据报到已知地址Q如果不调用bindQ服务器q程无法在某个已知地址上接受TCPq接或接收UDP数据报。客戯E也能调用bindQ这样便可以由应用程序而非内核来选择一个本地地址Q其l果是只能接收目的地址l定地址的数据包Q但通常不必调用bindQ因为内怼自动军_外出地址和时端口?br /> <span style="color: #008000"><strong>3. 对于tcp和udp协议的插口,调用connect有什么区别联p?</strong></span><br />    共同Ҏ讑֮插口的外部地址(插口的地址存储在相关的协议控制块中)Q不同点如下<br />    1QtcpQ与q端pȝq行3ơ握手交互,如果插口是非d的且q接正在q行中,那么q回EINPROGRESSQ下ơ再调用则返回EALREADYQ如果连接成功,无论是否dQ那么下ơ再调用会返回EISCONNQ如果连接失败,那么下次再调用,则重新开始三ơ握手?br />    2QudpQ没?ơ握手交互,直接讑֮外部地址Q无论插口是否阻塞,调用会立卌回,多次调用则会替换老的外部地址。发送数据必M用write或目的地址为空的sendtoQ若sendto目的地址非空Q则q回EISCONN。如果没有事先调用connectQ那么调用目的地址为空的sendto则会q回ENOTCONN?br /> <span style="color: #008000"><strong>4. 什么情况下调用close会阻塞?</strong></span><br />    q接已徏立且讄了SO_LINGER选项qg时值非零的d插口?br /> <span style="color: #008000"><strong>5. 插口IO有哪些系l调用?</strong></span><br />    发送有write、writev、sendto和sendmsgQ接收有read、readv、recvfrom和recvmsg。注意,send和recv是库函数而非pȝ调用Q前者调用sendto实现Q后者调用recvfrom实现?br /> <span style="color: #008000"><strong>6. write、writev、read、readv与sendto、sendmsg、recvfrom、recvmsg有什么不同?</strong></span><br />    1Q前?个适合于Q何描q符Q而后?个只能用于插口?br />    2Q前?个不支持标志Q而后?个支持?br />    3Q前面前2个不支持目的地址、后2个不支持源地址Q而后面前2个支持目的地址、后2个支持源地址?br />    4Q前?个不支持控制信息Q而后面第2个和W?个支持?br /> <span style="color: #008000"><strong>7. 如何断开已连接的udp插口Q允许调用sendto向其它主机发送数据?</strong></span><br />     ׃pȝq没有提供Ş如disconnect的断qAPIQ但connect内部实现是先断连Q再调用对应协议的PRU_CONNECTh处理Q因此向connect传递无效的外部地址l构(如IP=0.0.0.0QPort=0)Q虽然这样会Dl果p|Q但先前的断q成功,对应pcb的外部地址被设为INADDR_ANYQ所以调用sendto׃会返回EISCONN?br /> <br /> <span style="color: #ff6600; font-size: 12pt">【Raw IP?/span><br /> <span style="color: #008000"><strong>1. 怎么使用原始IPQ它有哪些用途及应用Q?/strong></span><br />    创徏SOCK_RAWcd的原始插口,p使用原始IP机制Q它有下列用途:<br />    1Q发送和接收ICMP和IGMP报文Q如pingE序和多播\由守护程序?br />    2Q构造自qIP首部Q如路由跟踪E序?br />    3Q设计基于IP的新的传输层协议Q如gatedE序?br /> <span style="color: #008000"><strong>2. 协议gؓPROTOCOL_RAW(255)的原始插口能收到什么类型的IP数据报?</strong></span><br />    ׃255是非零的保留|q样的IP数据报在|络中不会存在,原始IP输入处理协议比较试p|Q因此收不到Mcd的IP数据报?br /> <span style="color: #008000"><strong>3. 协议gؓ0的原始插口能收到什么类型的IP数据报?</strong></span><br />    ׃协议gؓ0Q原始IP输入处理忽略了协议比较测试,因此能收CQ何类型的IP数据报?br /> <span style="color: #008000"><strong>4. 如何处理收到的IP数据报?</strong></span><br />    遍历Internet PCB表,依次从协议倹{本地地址和外部地址三项来比较IP数据报和每个PCBQ将IP数据报复制追加到所有匹配的PCB对应的插口缓存中Qƈ唤醒{待的进E?br /> <span style="color: #008000"><strong>5. 如何发送数据?</strong></span><br />    先填充IP首部Q如果未讄IP_HDRINCL选项Q那么由内核填充Q否则由应用E序在发送前填充Q再交给IP协议输出处理?br /> <span style="color: #008000"><strong>6. 内核何时会调用原始输入?</strong></span><br />    当收到的协议cd为除IPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMP和IPPROTO_IGMP外的IP数据报时调用?br /> <br /> <span style="color: #ff6600; font-size: 12pt">【Unix domain?/span><br /> <span style="color: #008000"><strong>1. 使用unix域的原因有哪些?</strong></span><br />    1Q当通信双方在同一L上时Q用unix域插口的速度比tcp和udp插口要快很多?br />    2Q支持同一Lq程间传递描q符?br /> <span style="color: #008000"><strong>2. unix域和internet域有什么不同?</strong></span><br />    1Q编址l构不同Q前者是sockaddr_unQ与文gpȝ路径名关联,而后者是sockaddr_inQ与IP地址和端口关联?br />    2Q协议控制块不同Q前者是unpcbQ没有全局的pcb链表Q而后者是inpcbQ有全局的pcb双向循环链表?br /> <span style="color: #008000"><strong>3. 如果一个unix域服务器在bind后unlink了被l定的\径名Q会发生什么情况?</strong></span><br /> <div>   因ؓconnect内部实现查找路径名失败,所以连接失败,但listen会成功,因ؓbind会创建新的vnode和pcb兌Q且PRU_LISTENh实现只检查vnode是否为空?br /> <span style="color: #008000"><strong>4. 如果一个unix域服务器在终止时没有unlink被绑定的路径名,会发生什么情况?</strong></span><br />    因ؓconnect内部实现虽能扑ֈ路径名但找不到相关的插口Q所以连接被拒绝?br /> <span style="color: #008000"><strong>5. pȝ调用socketpair和pipe有什么区别联p?</strong></span><br />    共同Ҏ使用unix域,即socket调用W?参数为AF_UNIXQ不同点如下<br />    1Q前者是双工的,因ؓ两个插口标志都ؓdQ且它们的pcb怺指向ҎQ后者是单工的,因ؓ一个插口标志ؓ只读Q另一个ؓ只写Q写插口的pcb指向L口的pcb?br />    2Q前者支持数据报和流式插口,后者仅支持式插口?br /> <span style="color: #008000"><strong>6. unix域是怎么实现传递描q符的?</strong></span><br />    描述W存储在控制信息cmsghdr内,cms_level=SOL_SOCKET且cms_type=SCM_RIGHTSQunix域的发送请求实现将描述W{换ؓfile指针Q这个过E叫内部化,接收h实现把file指针转换为最的没有使用的描q符Q这个过E叫外部化?</div><img src ="http://m.shnenglu.com/qinqing1984/aggbug/202876.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2013-09-03 15:52 <a href="http://m.shnenglu.com/qinqing1984/archive/2013/09/03/202876.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TCP/IP FAQ Q?Q:链\层、网l层和传输层http://m.shnenglu.com/qinqing1984/archive/2013/08/25/202734.html春秋十二?/dc:creator>春秋十二?/author>Sun, 25 Aug 2013 02:50:00 GMThttp://m.shnenglu.com/qinqing1984/archive/2013/08/25/202734.htmlhttp://m.shnenglu.com/qinqing1984/comments/202734.htmlhttp://m.shnenglu.com/qinqing1984/archive/2013/08/25/202734.html#Feedback1http://m.shnenglu.com/qinqing1984/comments/commentRss/202734.htmlhttp://m.shnenglu.com/qinqing1984/services/trackbacks/202734.html
【Data Link?/span>
1. 环回接口地址必须?27.0.0.1吗?
   形如127.x.x.x的AcIP都可作ؓ环回接口的地址Q但常用的是127.0.0.1?br /> 2. 环回接口Z么没有输入处理?
   发送到环回接口的数据报实质上被送到|络层的输入队列中,因此数据报没有离开|络Q也׃可能从链路上接收到目标地址为环回接口地址的数据Q所以不存在输入处理?br /> 3. SLIP、环回和以太|接口,三者有何不同?
   SLIP和环回接口没有链路层首部和硬件地址Q环回接口没有输入处理,而以太网接口都有?br /> 4. SLIP和以太网接口如何分用输入帧,环回接口如何分用输出分组Q?/strong>
   SLIP直接放进IP输入队列中,以太|接口则Ҏ帧类型字D|到对应的协议输入队列中,环回接口则按目的地址族放到对应的输入队列中?br /> 5. 接口和地址有什么关联?
   一个接口的~址信息包括L地址、广播地址和网l掩码,当内核初始化Ӟ每个接口分配一个链路层地址Q可以配|有多个相同或不同的|络层地址Q例?个IP地址Q或?个IP地址?个OSI地址?br />
【ARP & RARP?br /> 1. 何时发送ARPhQ何时应{ARPhQ?/strong>
   当单播发送IP数据q且查询ARP高速缓存失败时Q就会广播一个询问目的主机硬件地址的ARPhQ当接收到ARPh的主机就是该h所要查扄目的L或目的主机的ARP代理服务器时Q就会单播一个ARP应答?br /> 2. Z么两者的以太|cd不同Q?/strong>
   ARPgؓ0x0806QRARP?x8035Q其实对于发送方来说Q利用ARP的op字段可以区分RARPQ但对于接收方,׃ARP实现在内怸Q而RARP一般实Cؓ服务器,所以ؓ了更易区分,单独用另一个值标识?br /> 3. 设计RARP服务器有哪些问题Q?/strong>
   一是怎么发送以太网帧以响应hQ这与系l相兟뀂二是当存在多个服务器时Q同时发送响应会造成以太|冲H,q可以通过分主从服务器和随机g时来优化避免?br /> 4. ARP在等待应{时Q它会如何处理发往l定目的的多个报文?
   在大多数的实CQ在{待一个ARP应答Ӟ只将最后一个报文发l特定目的主机。Host Requirements RFC要求实现中必防止这U类型的ARPz泛Q徏议最高速率是每U一ơ?br /> 5. 免费ARP有什么作用?
   一般的ARPh用于查询目标g地址Qƈ{待应答。而免费的ARP发出hq不一定期望应{,q可以有两方面的作用Q?br />    1Q一个主机可以确定是否存在相同IP地址的另一L
   2Q当本机g地址改变Ӟ通知其它L更新ARP高速缓存?br /> 6. ARP如何映射一个IP多播地址Q?/strong>
   先获取IP多播地址的低23位,再与帔R0x01005e7f0000按位或,l果是对应的多播硬件地址?br />
【IP?/span>
1. 何时何地分片Q?/strong>
   当数据报长度大于链\接口MTU且DF=0Ӟ开始分片,分片可发生在源主机,也可发生在中途\由器。若需要分片但DF=1Q则向源L发送ICMP不可辑ַ错?br /> 2. 如何分片Q?/strong>
   1Q?/span>计算每个分片的数据长?不含IP首部)Q除后一个分片外Q其它分片数据长度ؓ8字节的倍数?/span>
   2Q除复制对应数据外,q复制原始分l的首部?部分)选项到新的每个分片中Q更新新分片首部的头部长度、总长度、MF标志和偏U量。如果原始分l已l是分片Q那么MF=1Q否则最后一个分片MF=0Q其余MF=1?br /> 3. 何时何地重装Q?/strong>
   ׃分片可以有不同的路由Q而且中途\由器可能再次分片Q因此只有目标主机才能重装所有分片。当接收端第一ơ收C个MF或偏U量非零的分l时Q则该分l就是一个必被重装的分片,于是开始重装?/div> 4. 如何重装Q?/strong>
   1Q?元组{源地址Q目标地址Q协议,16位标识}为唯一标识查找当前分片所属的数据?分片?Q如果没有找刎ͼ则创建分片表Q按偏移量将当前分片插入到分片表Qƈ启动重装定时器?br />    2Q如果重装定时器时后,q没有组装好一个完整的IP数据报,此时如果已经收到W一个分片,则向源主回ICMP时差错Q最后丢弃收到的所有分片;否则Q提交数据给适当的传输层处理?br /> 5. 哪些分组能被转发Q何时{发?
   到达非最l目的地pȝ的分l,且当pȝ配置为可转发或分l包含源路由Ӟ才能被{发,但下列类型的分组除外Q?Q链路层q播 2Q环回分l?3Q网l?和Ecȝ标地址 4QDcȝ标地址?br />
【ICMP?/span>
1. ICMP报文有哪些类型,何时何地生成q些报文Q?/strong>
   包括h、应{、差错和重定?U,其中前两者可l一为查询类。请求当需要查询的时候由q程生成Q应{由当内核收到请求报文时生成Q当L发出的数据报无法成功地提交给目的LӞ目的L或中间\由器的IP或传输协议生成差错报文,q返回给原来的系l?br /> 2. 内核怎么处理收到的ICMP报文Q?/strong>
   ICMP是一U传输层协议Q其协议号ؓ1Q当IP层收C个ICMP报文Ӟ分用交给ICMP协议输入处理QICMP协议输入Ҏ其类型分别处理:1Q请?--生成适当的应{报?2Q差?--提交l适当的传输层协议处理 3Q应{?--提交l等待ICMP报文的进E?4Q重定向---更新路由表,q提交给{待的进E?br /> 3. 怎么发送ICMP报文Q?/strong>
   构造ICMP报文-->计算ICMP验和-->装到IP数据报中-->提交lIP协议输出处理Q对于用戯E,M用原始IP机制才能发送?br /> 4. 哪些情况不会产生ICMP差错报文Qؓ什么?
   1QICMP差错报文Q违反此条可能导致差错引起差错,无休止@环下厅R?br />    2Q源地址不是单播地址的IP数据报:q反此条D差错可能同时发到多个L?br />    3Q目的地址是广播或多播地址的IP数据报:q反此条D多个L可能同时响应?br />    4Q作为链路层q播的数据报Q违反此条导致多个主机可能同时响应?br />    5Q不是IP分片的第一片:q反此条可能D产生多个ICMP差错Q每个分片一个?br />    由此可见Q违反以上几条都会引Ll风暴?br />
【TCP & UDP?/span>
1. Z么TCP首部存在首部长度字段Q而UDP却没有?
   TCP首部存在选项Q如mss,timestame,nop和wscale{?br /> 2. Z么这两种协议首部前面都是源和目的端口Q?/strong>
   当TCP收到一个ICMP差错Ӟ必须查两个端口号以决定差错对应于哪个q接Q只有当UDP套接口连接到对端Ӟ用户q程才会收到ICMP差错Q例如当服务器未q行Ӟq回的ICMP端口不可达消息?br /> 3. 当收到TCP或UDP数据包时Q怎么提交l应用层Q?/strong>
   插口pE调用socket或accept创徏Q关联到对应的PCB(协议控制?上,通配匚w数由本地和外部IP地址定Q有3U取|0--本地和外部IP都不??--本地或外部IP有一个ؓ*?--本地和外部IP都ؓ*。与UDP不同的是QTCPq有自己的PCB?br />    1QTCPQ先扫描Internet PCBQ查找最通配匚w数的插口Q如果没扑ֈQ那么响应RST包;再查看对应的TCP PCBQ若不存在则响应RST包,否则若TCP 状态ؓ关闭Q则丢弃Q最后交付给扑ֈ的对应插口?br />    2QUDPQ这里要?U情况,对于目的Cؓq播或多播地址的IP数据报,交付l所有匹配的插口Q对于目的地为单播的IP数据报,扫描Internet PCBQ查扑օ有最通配匚w数的插口Q如果没有找刎ͼ则向源主机发送ICMP端口不可辑ַ错。如果有多个插口有相同的最通配匚w敎ͼ那么具体由哪个插口接收依赖于不同的实现?br /> 4. 计算首部验和ӞZ么要引入伪首部?
   q是因ؓ考虑到IP层的可能差错QTCP和UDP需要验证数据包是否被递送到正确的协议和目的L?br /> 5. UDP何时会计检验和Q如何区分是否用了验和Q?/strong>
   UDP的检验和是可选的Q当pȝ没有止(udpcksum非零)Ӟ发送方会计检验和Q接收方q须输入分组验和非零时才会计检验和。如果检验和字段非零Q那么就使用了,反之没有?br /> 6. 在TCP状态迁UMQ哪些状态在什么情况下可直接{到CLOSED状态?
   SYN_SENT在连接定时器时后,FIN_WAIT_2在FIN_WAIT_2定时器超时后?br /> 7. Z么TCP需要持l?persist)定时器、FIN_WAIT_2定时器和2MSL定时器?
   1Q因接对端发送的H口通告为ACK报文Q而ACK是不会确认的Q允许TCPl箋发送数据的H口更新可能会丢失,所以需要设定persist定时器,在超时后发?字节的数据,判定对端接收H口是否已打开?br />    2Q因为在正常情况下,当连接主动关闭时Q会由FIN_WAIT_1状态进入FIN_WAIT_2状态等待接收对端的FIN报文Q但Ҏ可能一直不发送FINQ所以需要FIN_WAIT_2定时器避免连接永q滞留在FIN_WAI_2状态?br />    3Q因为当q接d关闭q入TIME_WAIT状态后Q将{待2个MSL旉Q在q段旉内,TCP可以重发丢失的ACKQ丢弃来自新q接替n的迟到的报文D以防止被曲解,所以需?MSL定时器,时后关闭连接?br /> 8. 当TCP发送数据,调用ip_outputq回ENOBUFS差错Ӟ可能会发生什么情况?
   当提交给|络层因为内存不_送失败时Q数据包被丢弃。如果丢弃的是数据报文,重传定时器超时后数据被重传Q如果丢弃的是纯ACK报文Q对端收不到ACK时会重传对应的数据报文;如果丢弃的是RST报文Q当对端重传D发送RST报文的数据报文时Q将再次生成RST报文?br /> 9. TCP何时发送ACK报文Q?/strong>
   对于数据、SYN和FIN报文Q发送ACKQ但对于UACK和RST报文Q不会发送;另外当遇以下情况Ӟ则立卛_送?br />    1Q?00ms延时ACK定时器超Ӟ2Q收到失序的报文D;3Q三ơ握手收CSYNQ?Q收CFIN?br /> 10. TCP何时发送RST报文Q?/strong>
   1Q当收到报文D,但没有找到对应的internet pcb或tcp pcb?br />    2Q当q接处于LISTEN状态时Q收CACK报文Dc?br />    3Q当q接处于SYS_SENT状态时Q收C错误的ACK报文D?ack于{于iss或大于snd_max)?br />    4Q当q接被动关闭?状态大于CLOSE_WAIT)Q收C数据?br />    5Q当q接处于SYN_RCVD状态时Q收C错误的ACK报文D?ack于snd_una或大于snd_max)?img src ="http://m.shnenglu.com/qinqing1984/aggbug/202734.html" width = "1" height = "1" />

]]>q用状态机异步接收变长?/title><link>http://m.shnenglu.com/qinqing1984/archive/2012/09/20/191396.html</link><dc:creator>春秋十二?/dc:creator><author>春秋十二?/author><pubDate>Thu, 20 Sep 2012 07:48:00 GMT</pubDate><guid>http://m.shnenglu.com/qinqing1984/archive/2012/09/20/191396.html</guid><wfw:comment>http://m.shnenglu.com/qinqing1984/comments/191396.html</wfw:comment><comments>http://m.shnenglu.com/qinqing1984/archive/2012/09/20/191396.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://m.shnenglu.com/qinqing1984/comments/commentRss/191396.html</wfw:commentRss><trackback:ping>http://m.shnenglu.com/qinqing1984/services/trackbacks/191396.html</trackback:ping><description><![CDATA[     摘要: 情景分析    在网l编E中Q通常异步比同步处理更为复杂,但由于异步的事g通知机制Q避免了同步方式中的忙等待,提高了吞吐量Q因此效率较高,在高性能应用开发中Q经常被用到。而在处理异步相关的问题时Q状态机模式是一U典型的有效ҎQ这在libevent、memcached、nginx{开源Y??中多ơ被使用而得到见证。据此,为抛砖引玉,本文展示了用此Ҏ异步接收?..  <a href='http://m.shnenglu.com/qinqing1984/archive/2012/09/20/191396.html'>阅读全文</a><img src ="http://m.shnenglu.com/qinqing1984/aggbug/191396.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.shnenglu.com/qinqing1984/" target="_blank">春秋十二?/a> 2012-09-20 15:48 <a href="http://m.shnenglu.com/qinqing1984/archive/2012/09/20/191396.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一U简单的跨^台套接字道http://m.shnenglu.com/qinqing1984/archive/2012/06/17/179103.html春秋十二?/dc:creator>春秋十二?/author>Sat, 16 Jun 2012 19:02:00 GMThttp://m.shnenglu.com/qinqing1984/archive/2012/06/17/179103.htmlhttp://m.shnenglu.com/qinqing1984/comments/179103.htmlhttp://m.shnenglu.com/qinqing1984/archive/2012/06/17/179103.html#Feedback3http://m.shnenglu.com/qinqing1984/comments/commentRss/179103.htmlhttp://m.shnenglu.com/qinqing1984/services/trackbacks/179103.html阅读全文

]]>
Ʒһþ㽶߿ | 91Ʒ9lþþþ| Ʒþþþþø69| þ99þëƬһ| 97㽶þҹɫƷ| 99þһa| պӰþþñ| 99þþƷëƬѲ| þav뾫Ʒ˳| þ99ƷСѼ| þþþ޾Ʒþþþþþ | þþ| ٸþþþþþþþ| þѹۿƵ| 99þþƷѿһ | 99þĻ| Ʒ99þþþƷ| þþþþƷĻ| vĻþ| þþƷav| պƷھþ | ҹƷþ| Ʒþþþþþö| Ʒtvþþþþþ| 99þþþƷѹۿ| ޹ŷۺϾþ| ҹƷþ| þþþþһƷ| þþþþۺһĻ| Ʒһþ㽶߿| AVþþƷݺݰ˳| þۺɫɫ| ŷպƷþþѹۿ| &#228;v뾫Ʒþþ| þþƷƷƾ| 鶹þ| ۺ˾þôý| ӰȷŮAV³ɫԴþ| AVþþƷ| Ʒ޾þþþþ888| 2022Ʒþþþ|