??xml version="1.0" encoding="utf-8" standalone="yes"?>中文有码在线观看,国产亚洲欧美一区二区三区,精品午夜一区二区三区http://www.aygfsteel.com/xiaomage234/category/38027.html生命本就是一ơ凄的漂流Q记忆中放不下的Q永q是孩提时代的那一份浪漫与U真Q?/description>zh-cnThu, 07 Jul 2016 09:05:51 GMTThu, 07 Jul 2016 09:05:51 GMT60Android微信心蟩Ҏ【{?/title><link>http://www.aygfsteel.com/xiaomage234/archive/2016/07/07/431118.html</link><dc:creator>马?/dc:creator><author>马?/author><pubDate>Thu, 07 Jul 2016 08:09:00 GMT</pubDate><guid>http://www.aygfsteel.com/xiaomage234/archive/2016/07/07/431118.html</guid><wfw:comment>http://www.aygfsteel.com/xiaomage234/comments/431118.html</wfw:comment><comments>http://www.aygfsteel.com/xiaomage234/archive/2016/07/07/431118.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/xiaomage234/comments/commentRss/431118.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/xiaomage234/services/trackbacks/431118.html</trackback:ping><description><![CDATA[     摘要: from:http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=207243549&idx=1&sn=4ebe4beb8123f1b5ab58810ac8bc5994&scene=0#rd前言Q在13q?1月中旬时Q因为基lglh手紧张,Leo安排我和春哥d州轮岗支援。刚到广州的时候,Ray让我和春哥对Line...  <a href='http://www.aygfsteel.com/xiaomage234/archive/2016/07/07/431118.html'>阅读全文</a><img src ="http://www.aygfsteel.com/xiaomage234/aggbug/431118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/xiaomage234/" target="_blank">马?/a> 2016-07-07 16:09 <a href="http://www.aygfsteel.com/xiaomage234/archive/2016/07/07/431118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lvs之NAT、DR、TUN三种模式的应用配|案例[转]http://www.aygfsteel.com/xiaomage234/archive/2015/09/02/427100.html马?/dc:creator>马?/author>Wed, 02 Sep 2015 08:07:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2015/09/02/427100.htmlhttp://www.aygfsteel.com/xiaomage234/comments/427100.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2015/09/02/427100.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/427100.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/427100.html阅读全文

]]>
Java版的各种Thrift server实现的比??http://www.aygfsteel.com/xiaomage234/archive/2015/03/12/423410.html马?/dc:creator>马?/author>Thu, 12 Mar 2015 09:25:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2015/03/12/423410.htmlhttp://www.aygfsteel.com/xiaomage234/comments/423410.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2015/03/12/423410.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/423410.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/423410.html阅读全文

]]>
Apache Thrift - java开发详解E转]http://www.aygfsteel.com/xiaomage234/archive/2015/03/12/423409.html马?/dc:creator>马?/author>Thu, 12 Mar 2015 09:20:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2015/03/12/423409.htmlhttp://www.aygfsteel.com/xiaomage234/comments/423409.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2015/03/12/423409.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/423409.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/423409.html1、添加依?jar

<dependency>   <groupId>org.apache.thrift</groupId>   <artifactId>libthrift</artifactId>   <version>0.8.0</version> </dependency> <dependency>   <groupId>org.slf4j</groupId>   <artifactId>slf4j-log4j12</artifactId>   <version>1.6.1</version> </dependency> 

2、编写IDL文g Hello.thrift

namespace java service.demo
service Hello {
    string helloString(1:string para)
    i32 helloInt(1:i32 para)
    bool helloBoolean(1:bool para)
    void helloVoid()
    string helloNull()
}


3、生成代?/span>

thrift -o <output directory> -gen java Hello.thrift
生成代码~略图:



4、编写实现类、实现Hello.IfaceQ?/span>

~略图:



5、编写服务端Q发布(d式IO + 多线E处理)服务?/span>

  1. /** 
  2.      * d式、多U程处理 
  3.      *  
  4.      * @param args 
  5.      */  
  6.     @SuppressWarnings({ "unchecked", "rawtypes" })  
  7.     public static void main(String[] args) {  
  8.         try {  
  9.             //讄传输通道Q普通通道  
  10.             TServerTransport serverTransport = new TServerSocket(7911);  
  11.               
  12.             //使用高密度二q制协议  
  13.             TProtocolFactory proFactory = new TCompactProtocol.Factory();  
  14.               
  15.             //讄处理器HelloImpl  
  16.             TProcessor processor = new Hello.Processor(new HelloImpl());  
  17.               
  18.             //创徏服务?nbsp; 
  19.             TServer server = new TThreadPoolServer(  
  20.                     new Args(serverTransport)  
  21.                     .protocolFactory(proFactory)  
  22.                     .processor(processor)  
  23.                 );  
  24.               
  25.             System.out.println("Start server on port 7911...");  
  26.             server.serve();  
  27.         } catch (Exception e) {  
  28.             e.printStackTrace();  
  29.         }  
  30.     }  



6、编写客LQ调用(d式IO + 多线E处理)服务Q?/span>

  1. public static void main(String[] args) throws Exception {  
  2.         // 讄传输通道 - 普通IO通道  
  3.         TTransport transport = new TSocket("localhost", 7911);  
  4.         transport.open();  
  5.           
  6.         //使用高密度二q制协议  
  7.         TProtocol protocol = new TCompactProtocol(transport);  
  8.           
  9.         //创徏Client  
  10.         Hello.Client client = new Hello.Client(protocol);  
  11.           
  12.         long start = System.currentTimeMillis();  
  13.         for(int i=0; i<10000; i++){  
  14.             client.helloBoolean(false);  
  15.             client.helloInt(111);  
  16.             client.helloNull();  
  17.             client.helloString("dongjian");  
  18.             client.helloVoid();  
  19.         }  
  20.         System.out.println("耗时Q? + (System.currentTimeMillis() - start));  
  21.           
  22.         //关闭资源  
  23.         transport.close();  
  24.     }  



现在已完成整个开发过E,无敌单?/p>

其中服务端用的协议需要与客户端保持一?/strong>?/p>

-------------------------------------------------------------------------------------------------------------------


上面展示了普通且常用的服务端和客LQ下面请看非dIOQ即java中的NIOQ?/p>


Z非阻塞IOQNIOQ的服务?/strong>Q?/p>

  1. public static void main(String[] args) {  
  2.         try {  
  3.             //传输通道 - 非阻塞方?nbsp; 
  4.             TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(7911);  
  5.               
  6.             //异步IOQ需要用TFramedTransportQ它分块缓存读取?nbsp; 
  7.             TTransportFactory transportFactory = new TFramedTransport.Factory();  
  8.               
  9.             //使用高密度二q制协议  
  10.             TProtocolFactory proFactory = new TCompactProtocol.Factory();  
  11.               
  12.             //讄处理?nbsp;HelloImpl  
  13.             TProcessor processor = new Hello.Processor(new HelloImpl());  
  14.               
  15.             //创徏服务?nbsp; 
  16.             TServer server = new TThreadedSelectorServer(  
  17.                     new Args(serverTransport)  
  18.                     .protocolFactory(proFactory)  
  19.                     .transportFactory(transportFactory)  
  20.                     .processor(processor)  
  21.                 );  
  22.               
  23.             System.out.println("Start server on port 7911...");  
  24.             server.serve();  
  25.         } catch (Exception e) {  
  26.             e.printStackTrace();  
  27.         }  
  28.     }  



调用非阻塞IOQNIOQ服务的客户?/strong>Q?/p>

  1. public static void main(String[] args) throws Exception {  
  2.         //讄传输通道Q对于非d服务Q需要用TFramedTransportQ它数据分块发?nbsp; 
  3.         TTransport transport = new TFramedTransport(new TSocket("localhost", 7911));  
  4.         transport.open();  
  5.           
  6.         //使用高密度二q制协议  
  7.         TProtocol protocol = new TCompactProtocol(transport);  
  8.           
  9.         //创徏Client  
  10.         Hello.Client client = new Hello.Client(protocol);  
  11.           
  12.         long start = System.currentTimeMillis();  
  13.         for(int i=0; i<10000; i++){  
  14.             client.helloBoolean(false);  
  15.             client.helloInt(111);  
  16.             client.helloNull();  
  17.             client.helloString("360buy");  
  18.             client.helloVoid();  
  19.         }  
  20.         System.out.println("耗时Q? + (System.currentTimeMillis() - start));  
  21.           
  22.         //关闭资源  
  23.         transport.close();  
  24.     }  



-----------------------------------------------------------------------------------------------------------------------------------

客户端异步调?/strong>Q?/p>

  1. /** 调用[非阻塞IO]服务Q异?nbsp;*/  
  2.     public static void main(String[] args) {  
  3.         try {  
  4.             //异步调用理?nbsp; 
  5.             TAsyncClientManager clientManager = new TAsyncClientManager();  
  6.             //讄传输通道Q调用非dIO?nbsp; 
  7.             final TNonblockingTransport transport = new TNonblockingSocket("localhost", 7911);    
  8.             //讄协议  
  9.             TProtocolFactory protocol = new TCompactProtocol.Factory();    
  10.             //创徏Client  
  11.             final Hello.AsyncClient client = new Hello.AsyncClient(protocol, clientManager, transport);  
  12.             // 调用服务   
  13.             System.out.println("开始:" + System.currentTimeMillis());  
  14.             client.helloBoolean(false, new AsyncMethodCallback<Hello.AsyncClient.helloBoolean_call>() {  
  15.                 public void onError(Exception exception) {  
  16.                     System.out.println("错误1Q?nbsp;" + System.currentTimeMillis());  
  17.                 }  
  18.                 public void onComplete(helloBoolean_call response) {  
  19.                     System.out.println("完成1Q?nbsp;" + System.currentTimeMillis());  
  20.                     try {  
  21.                         client.helloBoolean(false, new AsyncMethodCallback<Hello.AsyncClient.helloBoolean_call>() {  
  22.                             public void onError(Exception exception) {  
  23.                                 System.out.println("错误2Q?nbsp;" + System.currentTimeMillis());  
  24.                             }  
  25.                               
  26.                             public void onComplete(helloBoolean_call response) {  
  27.                                 System.out.println("完成2Q?nbsp;" + System.currentTimeMillis());  
  28.                                 transport.close();  
  29.                             }  
  30.                         });  
  31.                     } catch (TException e) {  
  32.                         e.printStackTrace();  
  33.                     }  
  34.                 }  
  35.             });  
  36.             System.out.println("l束Q? + System.currentTimeMillis());  
  37.             Thread.sleep(5000);  
  38.         } catch (Exception e) {  
  39.             e.printStackTrace();  
  40.         }  
  41.     }  


-----------------------------------------------------------------------------------------------------------------------------------

使用SSL的服务端Q?/strong>



调用ZSSL服务端的客户端:




]]>
Netty版本升血泪史之线E篇http://www.aygfsteel.com/xiaomage234/archive/2015/02/10/422845.html马?/dc:creator>马?/author>Tue, 10 Feb 2015 04:03:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2015/02/10/422845.htmlhttp://www.aygfsteel.com/xiaomage234/comments/422845.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2015/02/10/422845.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/422845.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/422845.html

1. 背景

1.1. Netty 3.Xpd版本现状

Ҏ对NettyC֌部分用户的调查,l合Netty在其它开源项目中的用情况,我们可以看出目前Netty商用的主版本集中在3.X?.X上,其中以Netty 3.Xpd版本使用最为广泛?/p>

NettyC֌非常z跃Q?.Xpd版本?011q??日发布的netty-3.2.4 Final版本?014q?2?7日发布的netty-3.10.0 Final版本Q版本跨度达3q多Q期间共推出?1个Final版本?/p>

1.2. 升q是坚守老版?/h3>

相比于其它开源项目,Netty用户的版本升U之路更加艰辛,最Ҏ的原因就是Netty 4对Netty 3没有做到很好的前向兼宏V?/p>

׃版本不兼容,大多数老版本用者的x是既然升q么ȝQ我暂时又不需要用到Netty 4的新Ҏ,当前版本q挺E_Q就暂时先不升Q以后看看再说?/p>

坚守老版本还有很多其它的理由Q例如考虑到线上系l的E_性、对新版本的熟悉E度{。无论如何升UNetty都是一件大事,特别是对Netty有直接强依赖的品?/p>

从上面的分析可以看出Q坚守老版本似乎是个不错的选择Q但是,“理想是美好的,现实却是D酷?#8221;Q坚守老版本ƈ非L那么ҎQ下面我们就看下被迫升的案例?/p>

1.3. “被迫”升到Netty 4.X

除了Z使用新特性而主动进行的版本升Q大多数升都是“被迫?#8221;。下面我们对q些升原因q行分析?/p>

  1. 公司的开源Y件管理策略:对于那些大厂Q不同部门和产品U依赖的开源Y件版本经怸同,Z对开源依赖进行统一理Q降低安全、维护和理成本Q往往会指定优选的软g版本。由于Netty 4.X pd版本已经非常成熟Q因为,很多公司都优选Netty 4.X版本?/li>
  2. l护成本Q无论是依赖Netty 3.XQ还是Netty4.XQ往往需要在原框架之上做定制。例如,客户端的短连重连、心x、流控等。分别对Netty 4.X?.X版本实现两套定制框架Q开发和l护成本都非帔R。根据开源Y件的使用{略Q当存在版本冲突的时候,往往会选择升到更高的版本。对于NettyQ依焉循这个规则?/li>
  3. 新特性:Netty 4.X相比于Netty 3.X,提供了很多新的特性,例如优化的内存管理池、对MQTT协议的支持等。如果用户需要用这些新Ҏ,最便的做法是升Netty?.Xpd版本?/li>
  4. 更优异的性能QNetty 4.X版本相比?.X老版本,优化了内存池Q减了GC的频率、降低了内存消耗;通过优化RectorU程池模型,用户的开发更加简单,U程调度也更加高效?/li>

1.4. 升不当付出的代?/h3>

表面上看Q类库包路径的修攏VAPI的重构等g是升U的重头戏,大家往往把注意力攑ֈq些“明枪”上,但真正隐藏和致命的却?#8220;暗箭”。如果对Netty底层的事件调度机制和U程模型不熟悉,往往׃“中枪”?/p>

本文以几个比较典型的真实案例ZQ通过问题描述、问题定位和问题ȝQ让q些隐藏?#8220;暗箭”不再伤h?/p>

׃Netty 4U程模型改变D的升U事故还有很多,限于幅Q本文不一一枚DQ这些问题万变不d宗,只要抓住U程模型q个关键点,所谓的疑难杂症都将q刃而解?/p>

2. Netty升之后遭遇内存泄露

2.1. 问题描述

随着JVM虚拟机和JITx~译技术的发展Q对象的分配和回收是个非常轻量的工作。但是对于缓冲区BufferQ情况却E有不同Q特别是对于堆外直接内存的分配和回收Q是一件耗时的操作。ؓ了尽量重用缓冲区QNetty4.X提供了基于内存池的缓冲区重用机制。性能试表明Q采用内存池的ByteBuf相比于朝生夕灭的ByteBufQ性能?3倍左叻I性能数据与用场景强相关Q?/p>

业务应用的特Ҏ高ƈ发、短程Q大多数对象都是朝生夕灭的短生命周期对象。ؓ了减内存的拯Q用h望在序列化的时候直接将对象~码到PooledByteBuf里,q样׃需要ؓ每个业务消息都重新申请和释放内存?/p>

业务的相关代码示例如下:

//在业务线E中初始化内存池分配器,分配非堆内存  ByteBufAllocator allocator = new PooledByteBufAllocator(true);  ByteBuf buffer = allocator.ioBuffer(1024); //构造订购请求消息ƈ赋|业务逻辑省略 SubInfoReq infoReq = new SubInfoReq (); infoReq.setXXX(......); //对象编码到ByteBuf?codec.encode(buffer, info); //调用ChannelHandlerContextq行消息发?ctx.writeAndFlush(buffer);

业务代码升Netty版本q构之后,q行一D|_Javaq程׃宕机Q查看系l运行日志发现系l发生了内存泄露Q示例堆栈)Q?/p>

?-1 OOM内存溢出堆栈

对内存进行监控(切换使用堆内存池Q方便对内存q行监控Q,发现堆内存一直飙升,如下所C(CZ堆内存监控)Q?/p>

?-2 堆内存监?/p>

2.2. 问题定位

使用jmap -dump:format=b,file=netty.bin PID 堆内存dump出来Q通过IBM的HeapAnalyzer工具q行分析Q发现ByteBuf发生了泄霌Ӏ?/p>

因ؓ使用了内存池Q所以首先怀疑是不是甌的ByteBuf没有被释攑֯_查看代码Q发现消息发送完成之后,Netty底层已经调用ReferenceCountUtil.release(message)对内存进行了释放。这是怎么回事呢?NNetty 4.X的内存池有BugQ调用release操作释放内存p|Q?/p>

考虑到Netty 内存池自wBug的可能性不大,首先从业务的使用方式入手分析Q?/p>

  1. 内存的分配是在业务代码中q行Q由于用到了业务线E池做I/O操作和业务操作的隔离Q实际上内存是在业务U程中分配的Q?/li>
  2. 内存的释放操作是在outbound中进行,按照Netty 3的线E模型,downstreamQ对应Netty 4的outboundQNetty 4取消了upstream和downstreamQ的handler也是׃务调用者线E执行的Q也是说释放跟分配在同一个业务线E中q行?/li>

初次排查q没有发现导致内存泄露的根因Q一{莫展之际开始查看Netty的内存池分配器PooledByteBufAllocator的Doc和源码实玎ͼ发现内存池实际是ZU程上下文实现的Q相关代码如下:

final ThreadLocal<PoolThreadCache> threadCache = new ThreadLocal<PoolThreadCache>() {         private final AtomicInteger index = new AtomicInteger();         @Override         protected PoolThreadCache initialValue() {             final int idx = index.getAndIncrement();             final PoolArena<byte[]> heapArena;             final PoolArena<ByteBuffer> directArena;             if (heapArenas != null) {                 heapArena = heapArenas[Math.abs(idx % heapArenas.length)];             } else {                 heapArena = null;             }             if (directArenas != null) {                 directArena = directArenas[Math.abs(idx % directArenas.length)];             } else {                 directArena = null;             }             return new PoolThreadCache(heapArena, directArena);         }

也就是说内存的申请和释放必须在同一U程上下文中Q不能跨U程。跨U程之后实际操作的就不是同一块内存区域,q会D很多严重的问题,内存泄露便是其中之一。内存在AU程甌Q切换到BU程释放Q实际是无法正确回收的?/p>

通过对Netty内存池的源码分析Q问题基本锁定。保险v见进行简单验证,通过对单条业务消息进行DebugQ发现执行释攄果然不是业务U程Q而是Netty的NioEventLoopU程Q当某个消息被完全发送成功之后,会通过ReferenceCountUtil.release(message)Ҏ释放已经发送成功的ByteBuf?/p>

问题定位出来之后Ql溯源,发现Netty 4修改了Netty 3的线E模型:在Netty 3的时候,upstream是在I/OU程里执行的Q而downstream是在业务U程里执行。当Netty从网l读取一个数据报投递给业务handler的时候,handler是在I/OU程里执行;而当我们在业务线E中调用write和writeAndFlush向网l发送消息的时?handler是在业务U程里执行,直到最后一个Header handler消息写入到发送队列中Q业务线E才q回?/p>

Netty4修改了这一模型Q在Netty 4里inbound(对应Netty 3的upstream)和outbound(对应Netty 3的downstream)都是在NioEventLoop(I/OU程)中执行。当我们在业务线E里通过ChannelHandlerContext.write发送消息的时候,Netty 4在将消息发送事件调度到ChannelPipeline的时候,首先待发送的消息装成一个TaskQ然后放到NioEventLoop的Q务队列中Q由NioEventLoopU程异步执行。后l所有handler的调度和执行Q包括消息的发送、I/O事g的通知Q都由NioEventLoopU程负责处理?/p>

下面我们分别通过ҎNetty 3和Netty 4的消息接收和发送流E,来理解两个版本线E模型的差异Q?/p>

Netty 3的I/O事g处理程Q?/p>

?-3 Netty 3 I/O事g处理U程模型

Netty 4的I/O消息处理程Q?/p>

?-4 Netty 4 I/O事g处理U程模型

2.3. 问题ȝ

Netty 4.X版本新增的内存池实非常高效Q但是如果用不当则会导致各U严重的问题。诸如内存泄露这c问题,功能试q没有异常,如果相关接口没有q行压测或者稳定性测试而直接上U,则会D严重的线上问题?/p>

内存池PooledByteBuf的用徏议:

  1. 甌之后一定要记得释放QNetty自nSocketd和发送的ByteBufpȝ会自动释放,用户不需要做二次释放Q如果用户用Netty的内存池在应用中做ByteBuf的对象池使用Q则需要自׃动释放;
  2. 避免错误的释放:跨线E释放、重复释攄都是非法操作Q要避免。特别是跨线E申请和释放Q往往h隐蔽性,问题定位隑ֺ较大Q?/li>
  3. 防止隐式的申请和分配Q之前曾l发生过一个案例,Z解决内存池跨U程甌和释N题,有用户对内存池做了二ơ包装,以实现多U程操作Ӟ内存始终由包装的理U程甌和释放,q样可以屏蔽用户业务U程模型和访问方式的差异。谁知运行一D|间之后再ơ发生了内存泄露Q最后发现原来调用ByteBuf的write操作Ӟ如果内存定w不Q会自动q行定w扩展。扩展操作由业务U程执行Q这qq了内存池管理线E,发生?#8220;引用逃?#8221;。该Bug只有在ByteBuf定w动态扩展的时候才发生Q因此,上线很长一D|间没有发生,直到某一?.....因此Q大家在使用Netty 4.X的内存池时要格外当心Q特别是做二ơ封装时Q一定要对内存池的实现细节有深刻的理解?/li>

3. Netty升之后遭遇数据被篡?/h2>

3.1. 问题描述

某业务品,Netty3.X升?.X之后Q系l运行过E中Q偶现服务端发送给客户端的应答数据被莫?#8220;改”?/p>

业务服务端的处理程如下Q?/p>

  1. 解码后的业务消息封装成TaskQ投递到后端的业务线E池中执行;
  2. 业务U程处理业务逻辑Q完成之后构造应{消息发送给客户端;
  3. 业务应答消息的编码通过l承Netty的CodeC框架实现Q即Encoder ChannelHandler;
  4. 调用Netty的消息发送接口之后,程l箋Q根据业务场景,可能会l操作原发送的业务对象?/li>

业务相关代码CZ如下Q?/p>

//构造订购应{消?SubInfoResp infoResp = new SubInfoResp(); //Ҏ业务逻辑Q对应答消息赋?infoResp.setResultCode(0); infoResp.setXXX()Q?后箋赋值操作省?..... //调用ChannelHandlerContextq行消息发?ctx.writeAndFlush(infoResp); //消息发送完成之后,后箋Ҏ业务程q行分支处理Q修改infoResp对象 infoResp.setXXX(); 后箋代码省略......

3.2. 问题定位

首先对应{消息被非法“改”的原因进行分析,l过定位发现当发生问题时Q被“改”的内Ҏ调用writeAndFlush接口之后Q由后箋业务分支代码修改应答消息D的。由于修Ҏ作发生在writeAndFlush操作之后Q按照Netty 3.X的线E模型不应该出现该问题?/p>

在Netty3中,downstream是在业务U程里执行的Q也是说对SubInfoResp的编码操作是在业务线E中执行的,当编码后的ByteBuf对象被投递到消息发送队列之后,业务U程才会q回ql执行后l的业务逻辑Q此时修改应{消息是不会改变已完成编码的ByteBuf对象的,所以肯定不会出现应{消息被改的问题?/p>

初步分析应该是由于线E模型发生变更导致的问题Q随后查验了Netty 4的线E模型,果然发生了变化:当调用outbound向外发送消息的时候,Netty会将发送事件封装成TaskQ投递到NioEventLoop的Q务队列中异步执行Q相关代码如下:

@Override  public void invokeWrite(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {         if (msg == null) {             throw new NullPointerException("msg");         }         validatePromise(ctx, promise, true);         if (executor.inEventLoop()) {             invokeWriteNow(ctx, msg, promise);         } else {             AbstractChannel channel = (AbstractChannel) ctx.channel();             int size = channel.estimatorHandle().size(msg);             if (size > 0) {                 ChannelOutboundBuffer buffer = channel.unsafe().outboundBuffer();                 // Check for null as it may be set to null if the channel is closed already                 if (buffer != null) {                     buffer.incrementPendingOutboundBytes(size);                 }             }             safeExecuteOutbound(WriteTask.newInstance(ctx, msg, size, promise), promise, msg);         }     }

通过上述代码可以看出QNetty首先对当前的操作的线E进行判断,如果操作本n是由NioEventLoopU程执行Q则调用写操作;否则Q执行线E安全的写操作,卛_写事件封装成TaskQ放入到d队列中由Netty的I/OU程执行Q业务调用返回,程l箋执行?/p>

通过源码分析Q问题根源已l很清楚Q系l升U到Netty 4之后Q线E模型发生变化,响应消息的编码由NioEventLoopU程异步执行Q业务线E返回。这时存在两U可能:

  1. 如果~码操作先于修改应答消息的业务逻辑执行Q则q行l果正确Q?/li>
  2. 如果~码操作在修改应{消息的业务逻辑之后执行Q则q行l果错误?/li>

׃U程的执行先后顺序无法预,因此该问题隐藏的相当深。如果对Netty 4和Netty3的线E模型不了解Q就会掉入陷阱?/p>

Netty 3版本业务逻辑没有问题Q流E如下:

?-1 升之前的业务流E线E模?/p>

升到Netty 4版本之后Q业务流E由于NettyU程模型的变更而发生改变,D业务逻辑发生问题Q?/p>

?-2 升之后的业务处理流E发生改?/p>

3.3. 问题ȝ

很多读者在q行Netty 版本升的时候,只关注到了包路径、类和API的变_q没有注意到隐藏在背后的“暗箭”- U程模型变更?/p>

升到Netty 4的用户需要根据新的线E模型对已有的系l进行评伎ͼ重点需要关注outbound的ChannelHandlerQ如果它的正性依赖于Netty 3的线E模型,则很可能在新的线E模型中出问题,可能是功能问题或者其它问题?/p>

4. Netty升之后性能严重下降

4.1. 问题描述

怿很多Netty用户都看q如下相x告:

在TwitterQNetty 4 GC开销降ؓ五分之一QNetty 3使用Java对象表示I/O事gQ这L单,但会产生大量?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">垃圾Q尤其是在我们这L规模下。Netty 4在新版本中对此做Z更改Q取代生存周期短的事件对象,而以定义在生存周期长的通道对象上的Ҏ处理I/O事g。它q有一个用池的专用缓冲区分配器?/p>

每当收到C息或者用户发送信息到q程端,Netty 3均会创徏一个新的堆~冲区。这意味着Q对应每一个新的缓冲区Q都会有一?#8216;new byte[capacity]’。这些缓冲区会导致GC压力Qƈ消耗内存带宽:Z安全赯Q新的字节数l分配时会用零填充,q会消耗内存带宽。然而,用零填充的数l很可能会再ơ用实际的数据填充,q又会消耗同L内存带宽。如果Java虚拟机(JVMQ提供了创徏新字节数l而又无需用零填充的方式,那么我们本来可以将内存带宽消耗减?0%Q但是目前没有那样一U方式?/p>

在Netty 4中,代码定义了粒度更l的APIQ用来处理不同的事gcdQ而不是创Z件对象。它q实C一个新~冲池,那是一个纯Java版本?nbsp;jemalloc QFacebook也在用)。现在,Netty不会再因为用零填充缓冲区而浪费内存带宽了?/p>

我们比较了两个分别徏立在Netty 3?基础?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">echo协议服务器。(Echo非常单,q样QQ何垃圄产生都是Netty的原因,而不是协议的原因Q。我使它们服务于相同的分布式echo协议客户端,来自q些客户端的16384个ƈ发连接重复发?56字节的随载,几乎使千兆以太网饱和?/p>

Ҏ试l果QNetty 4Q?/p>

  • GC中断频率是原来的1/5Q?45.5 vs. 9.2?分钟
  • 垃圾生成速度是原来的1/5Q?207.11 vs 41.81 MiB/U?/strong>

正是看到了相关的Netty 4性能提升报告Q很多用户选择了升U。事后一些用户反馈Netty 4q没有跟产品带来预期的性能提升Q有些甚臌发生了非怸重的性能下降Q下面我们就以某业务产品的失败升U经历ؓ案例Q详l分析下D性能下降的原因?/p>

4.2. 问题定位

首先通过JMC{性能分析工具Ҏ能热点q行分析Q示例如下(信息安全{原因,只给出分析过E示例截图)Q?/p>

?-1 JMC性能监控分析

通过对热Ҏ法的分析Q发现在消息发送过E中Q有两处热点Q?/p>

  1. 消息发送性能l计相关Handler;
  2. ~码Handler?/li>

对用Netty 3版本的业务品进行性能Ҏ试Q发CqC个Handler也是热点Ҏ。既焉是热点,为啥切换到Netty4之后性能下降q么厉害呢?

通过Ҏ的调用树分析发现了两个版本的差异Q在Netty 3中,上述两个热点Ҏ都是׃务线E负责执行;而在Netty 4中,则是由NioEventLoop(I/O)U程执行。对于某个链路,业务是拥有多个线E的U程池,而NioEventLoop只有一个,所以执行效率更低,q回l客L的应{时延就大。时延增大之后,自然Dpȝq发量降低,性能下降?/p>

扑և问题根因之后Q针对Netty 4的线E模型对业务q行专项优化Q性能辑ֈ预期Q远过了Netty 3老版本的性能?/p>

Netty 3的业务线E调度模型图如下所C:充分利用了业务多U程q行~码和Handler处理的优势,周期T内可以处理N条业务消息?/p>

?-2 Netty 3业务调度性能模型

切换到Netty 4之后Q业务耗时Handler被I/OU程串行执行Q因此性能发生比较大的下降Q?/p>

?-3 Netty 4业务调度性能模型

4.3. 问题ȝ

该问题的根因q是׃Netty 4的线E模型变更引PU程模型变更之后Q不仅媄响业务的功能Q甚臛_性能也会造成很大的媄响?/p>

对Netty的升U需要从功能、兼Ҏ和性能{多个角度进行综合考虑Q切不可只盯着API变更q个芝麻Q而丢掉了性能q个西瓜。API的变更会D~译错误Q但是性能下降却隐藏于无Ş之中Q稍不留意就会中招?/p>

对于讲究快速交付、敏捷开发和灰度发布的互联网应用Q升U的时候更应该要当心?/p>

5. Netty升之后上下文丢?/h2>

5.1. 问题描述

Z提升业务的二ơ定制能力,降低Ҏ口的侵入性,业务使用U程变量q行消息上下文的传递。例如消息发送源地址信息、消息Id、会话Id{?/p>

业务同时使用C一些第三方开源容器,也提供了U程U变量上下文的能力。业务通过容器上下文获取第三方容器的系l变量信息?/p>

升到Netty 4之后Q业务承自Netty的ChannelHandler发生了空指针异常Q无论是业务自定义的U程上下文、还是第三方容器的线E上下文Q都获取不到传递的变量倹{?/p>

5.2. 问题定位

首先查代码,看业务是否传递了相关变量Q确认业务传递之后怀疑跟Netty 版本升相关Q调试发玎ͼ业务ChannelHandler获取的线E上下文对象和之前业务传递的上下文不是同一个。这p明执行ChannelHandler的线E跟处理业务的线E不是同一个线E!

查看Netty 4U程模型的相关Doc发现QNetty修改了outbound的线E模型,正好影响了业务消息发送时的线E上下文传递,最l导致线E变量丢失?/p>

5.3. 问题ȝ

通常业务的线E模型有如下几种Q?/p>

  1. 业务自定义线E池/U程l处理业务,例如使用JDK 1.5提供的ExecutorServiceQ?/li>
  2. 使用J2EE Web容器自带的线E模型,常见的如JBoss和Tomcat的HTTP接入U程{;
  3. 隐式的用其它第三方框架的线E模型,例如使用NIO框架q行协议处理Q业务代码隐式用的是NIO框架的线E模型,除非业务明确的实现自定义U程模型?/li>

在实践中我们发现很多业务使用了第三方框架Q但是只熟悉API和功能,对线E模型ƈ不清楚。某个类库由哪个U程调用Q糊里糊涂。ؓ了方便变量传递,又随意的使用U程变量Q实际对背后W三方类库的U程模型产生了强依赖。当容器或者第三方cd升之后Q如果线E模型发生了变更Q则原有功能׃发生问题?/p>

鉴于此,在实际工作中Q尽量不要强依赖W三方类库的U程模型Q如果确实无法避免,则必d它的U程模型有深入和清晰的了解。当W三方类库升U之后,需要检查线E模型是否发生变_如果发生变化Q相关的代码也需要考虑同步升?/p>

6. Netty3.X VS Netty4.X 之线E模?/h2>

通过对三个具有典型性的升p|案例q行分析和ȝQ我们发现有个共性:都是U程模型改变惹的?

下面节我们pl得对Netty3和Netty4版本的I/OU程模型q行ҎQ以方便大家掌握两者的差异Q在升和用中量踩雗?/p>

6.1 Netty 3.X 版本U程模型

Netty 3.X的I/O操作U程模型比较复杂Q它的处理模型包括两部分Q?/p>

  1. InboundQ主要包括链路徏立事件、链路激zM件、读事g、I/O异常事g、链路关闭事件等Q?/li>
  2. OutboundQ主要包括写事g、连接事件、监听绑定事件、刷C件等?/li>

我们首先分析下Inbound操作的线E模型:

?-1 Netty 3 Inbound操作U程模型

从上囑֏以看出,Inbound操作的主要处理流E如下:

  1. I/OU程QWorkU程Q将消息从TCP~冲取到SocketChannel的接收缓冲区中;
  2. 由I/OU程负责生成相应的事Ӟ触发事g向上执行Q调度到ChannelPipeline中;
  3. I/OU程调度执行ChannelPipeline中Handler铄对应ҎQ直C务实现的Last Handler;
  4. Last Handler消息封装成RunnableQ放入到业务U程池中执行QI/OU程q回Ql读/写等I/O操作Q?/li>
  5. 业务U程池从d队列中弹出消息,q发执行业务逻辑?/li>

通过对Netty 3的Inbound操作q行分析我们可以看出QInbound的Handler都是由Netty的I/O WorkU程负责执行?/p>

下面我们l箋分析Outbound操作的线E模型:

?-2 Netty 3 Outbound操作U程模型

从上囑֏以看出,Outbound操作的主要处理流E如下:

业务U程发vChannel Write操作Q发送消息;

  1. Netty写操作装成写事gQ触发事件向下传播;
  2. 写事件被调度到ChannelPipeline中,׃务线E按照Handler Chain串行调用支持Downstream事g的Channel Handler;
  3. 执行到系l最后一个ChannelHandlerQ将~码后的消息Push到发送队列中Q业务线E返回;
  4. Netty的I/OU程从发送消息队列中取出消息Q调用SocketChannel的writeҎq行消息发送?/li>

6.2 Netty 4.X 版本U程模型

相比于Netty 3.Xpd版本QNetty 4.X的I/O操作U程模型比较{,它的原理囑֦下所C:

?-3 Netty 4 Inbound和Outbound操作U程模型

从上囑֏以看出,Outbound操作的主要处理流E如下:

  1. I/OU程NioEventLoop从SocketChannel中读取数据报Q将ByteBuf投递到ChannelPipelineQ触发ChannelRead事gQ?/li>
  2. I/OU程NioEventLoop调用ChannelHandler链,直到消息投递到业务U程Q然后I/OU程q回Ql后l的d操作Q?/li>
  3. 业务U程调用ChannelHandlerContext.write(Object msg)Ҏq行消息发送;
  4. 如果是由业务U程发v的写操作QChannelHandlerInvoker发送消息封装成TaskQ放入到I/OU程NioEventLoop的Q务队列中Q由NioEventLoop在@环中l一调度和执行。放入Q务队列之后,业务U程q回Q?/li>
  5. I/OU程NioEventLoop调用ChannelHandler链,q行消息发送,处理Outbound事gQ直到将消息攑օ发送队列,然后唤醒SelectorQ进而执行写操作?/li>

通过程分析Q我们发现Netty 4修改了线E模型,无论是Inboundq是Outbound操作Q统一由I/OU程NioEventLoop调度执行?/p>

6.3. U程模型Ҏ

在进行新老版本线E模型PK之前Q首先还是要熟悉下串行化设计的理念:

我们知道当系l在q行q程中,如果频繁的进行线E上下文切换Q会带来额外的性能损耗。多U程q发执行某个业务程Q业务开发者还需要时dU程安全保持警惕Q哪些数据可能会被ƈ发修改,如何保护Q这不仅降低了开发效率,也会带来额外的性能损耗?/p>

Z解决上述问题QNetty 4采用了串行化设计理念Q从消息的读取、编码以及后lHandler的执行,始终都由I/OU程NioEventLoop负责Q这意外着整个程不会q行U程上下文的切换Q数据也不会面被ƈ发修改的风险Q对于用戯言Q甚至不需要了解Netty的线E细节,q确实是个非常好的设计理念,它的工作原理囑֦下:

?-4 Netty 4的串行化设计理念

一个NioEventLoop聚合了一个多路复用器SelectorQ因此可以处理成百上千的客户端连接,Netty的处理策略是每当有一个新的客L接入Q则从NioEventLoopU程l中序获取一个可用的NioEventLoopQ当到达数组上限之后Q重新返回到0Q通过q种方式Q可以基本保证各个NioEventLoop的负载均衡。一个客Lq接只注册到一个NioEventLoop上,q样避免了多个I/OU程dƈ发操作它?/p>

Netty通过串行化设计理念降低了用户的开发难度,提升了处理性能。利用线E组实现了多个串行化U程水^q行执行Q线E之间ƈ没有交集Q这h可以充分利用多核提升q行处理能力Q同旉免了U程上下文的切换和ƈ发保护带来的额外性能损耗?/p>

了解完了Netty 4的串行化设计理念之后Q我们l看Netty 3U程模型存在的问题,ȝhQ它的主要问题如下:

  1. Inbound和Outbound实质都是I/O相关的操作,它们的线E模型竟然不l一Q这l用户带来了更多的学习和使用成本Q?/li>
  2. Outbound操作׃务线E执行,通常业务会用线E池q行处理业务消息Q这意味着在某一个时M有多个业务线E同时操作ChannelHandlerQ我们需要对ChannelHandlerq行q发保护Q通常需要加锁。如果同步块的范围不当,可能会导致严重的性能瓉Q这对开发者的技能要求非帔RQ降低了开发效率;
  3. Outbound操作q程中,例如消息~码异常Q会产生ExceptionQ它会被转换成Inbound的Exceptionq知到ChannelPipelineQ这意味着业务U程发v了Inbound操作Q它打破了Inbound操作由I/OU程操作的模型,如果开发者按照Inbound操作只会׃个I/OU程执行的约束进行设计,则会发生U程q发讉K安全问题。由于该场景只在特定异常时发生,因此错误非常隐蔽Q一旦在生环境中发生此cȝEƈ发问题,定位隑ֺ和成本都非常大?/li>

讲了q么多,gNetty 4 完胜 Netty 3的线E模型,其实q不然。在特定的场景下QNetty 3的性能可能更高Q就如本文第4章节所Ԍ如果~码和其它Outbound操作非常耗时Q由多个业务U程q发执行Q性能肯定高于单个NioEventLoopU程?/p>

但是Q这U性能优势不是不可逆{的,如果我们修改业务代码Q将耗时的Handler操作前置QOutbound操作不做复杂业务逻辑处理Q性能同样不输于Netty 3Q但是考虑内存池优化、不会反复创建Event、不需要对Handler加锁{Netty 4的优化,整体性能Netty 4版本肯定会更高?/p>

总而言之,如果用户真正熟悉q掌握了Netty 4的线E模型和功能cdQ相信不仅仅开发会更加单,性能也会更优Q?/p>

6.4. 思?/h3>

Netty 而言Q掌握线E模型的重要性不亚于熟悉它的API和功能。很多时候我遇到的功能、性能{问题,都是׃~Z对它U程模型和原理的理解D的,l果我们׃讹传讹,认ؓNetty 4版本不如3好用{?/p>

不能说所有开源Y件的版本升一定都胜过老版本,Netty而言Q我认ؓNetty 4版本相比于老的Netty 3Q确实是历史的一大进步?/p>

7. 作者简?/h2>

李林锋,2007q毕业于东北大学Q?008q进入华为公总事高性能通信软g的设计和开发工作,?qNIO设计和开发经验,_NNetty、Mina{NIO框架和^C间gQ现dY件^台架构部架构师,《Netty权威指南》作者?/p>

联系方式Q新微?Nettying 微信QNettying 微信公众PNetty之家


感谢郭蕾Ҏ文的{划和审校?/p>

lInfoQ中文站投E或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也Ƣ迎大家通过新浪微博Q?a style="text-decoration: none; color: #286ab2; outline: none !important; margin: 0px; border: 0px; padding: 0px;">@InfoQQ或者腾讯微博(@InfoQQ关注我们,q与我们的编辑和其他读者朋友交?/p>

]]>TCP三次握手及四ơ挥手详l图?/title><link>http://www.aygfsteel.com/xiaomage234/archive/2013/06/24/400910.html</link><dc:creator>马?/dc:creator><author>马?/author><pubDate>Mon, 24 Jun 2013 08:33:00 GMT</pubDate><guid>http://www.aygfsteel.com/xiaomage234/archive/2013/06/24/400910.html</guid><wfw:comment>http://www.aygfsteel.com/xiaomage234/comments/400910.html</wfw:comment><comments>http://www.aygfsteel.com/xiaomage234/archive/2013/06/24/400910.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/xiaomage234/comments/commentRss/400910.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/xiaomage234/services/trackbacks/400910.html</trackback:ping><description><![CDATA[<div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> 相对于SOCKET开发?TCP创徏q程和链接折除过E是由TCP/IP协议栈自动创建的.因此开发者ƈ不需要控制这个过E?但是对于理解TCP底层q作机制,相当有帮?</div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">   而且对于有网l协议工E师之类W试,几乎是必考的内容.企业对这个问题热情之?Z我的意料Q?Q。有时上午面试前q个问题Qƈ重复讲一ơ,下午几乎每一个h都被问到q个问题?/div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">因此在这里详l解释一下这两个q程?/div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><strong style="margin: 0px; padding: 0px;"><span size="3" style="margin: 0px; padding: 0px; font-size: small;"><span style="margin: 0px; padding: 0px; text-decoration: underline;">TCP三次握手</span></span></strong></div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">所谓三ơ握?Three-way Handshake)Q是指徏立一个TCPq接Ӟ需要客L和服务器d发?个包?/div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">三次握手的目的是q接服务器指定端口,建立TCPq接,q同步连接双方的序列号和认号ƈ交换 TCP H口大小信息.在socket~程中,客户端执行connect()时。将触发三次握手?/div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </div><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><div align="center" style="margin: 0px;"> </div><div align="center" style="margin: 0px;"> </div><div align="center" style="margin: 0px;"> </div><div align="center" style="margin: 0px;"><img src="http://blogimg.chinaunix.net/blog/upfile2/100327002629.png" alt="" border="0" width="650" style="margin: 0px; padding: 0px; border: 0px;" /></div></div><ul style="margin: 0px 0px 0px 45px; padding: 0px; word-break: break-all; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><li style="margin: 0px; padding: 0px; list-style: inherit;">W一ơ握?<br style="margin: 0px; padding: 0px;" />客户端发送一个TCP的SYN标志位置1的包指明客户打算q接的服务器的端口,以及初始序号X,保存在包头的序列?Sequence Number)字段里?/li></ul><div align="center" style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><img src="http://blogimg.chinaunix.net/blog/upfile2/100327002911.png" alt="" border="0" style="margin: 0px; padding: 0px; border: 0px;" /></div><ul style="margin: 0px 0px 0px 45px; padding: 0px; word-break: break-all; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><li style="margin: 0px; padding: 0px; list-style: inherit;">W二ơ握?<br style="margin: 0px; padding: 0px;" />服务器发回确认包(ACK)应答。即SYN标志位和ACK标志位均?同时Q将认序号(Acknowledgement Number)讄为客LI S N??即X+1?/li></ul><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </p><p align="center" style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><img src="http://blogimg.chinaunix.net/blog/upfile2/100327003054.png" alt="" border="0" width="500" style="margin: 0px; padding: 0px; border: 0px;" /></p><ul style="margin: 0px 0px 0px 45px; padding: 0px; word-break: break-all; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><li style="margin: 0px; padding: 0px; list-style: inherit;">W三ơ握?<br style="margin: 0px; padding: 0px;" />客户端再ơ发送确认包(ACK) SYN标志位ؓ0,ACK标志位ؓ1.q且把服务器发来ACK的序号字D?1,攑֜定字段中发送给Ҏ.q且在数据段攑ֆISN?1</li></ul><div align="center" style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><img src="http://blogimg.chinaunix.net/blog/upfile2/100327003214.png" alt="" border="0" width="500" style="margin: 0px; padding: 0px; border: 0px;" /></div><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><strong style="margin: 0px; padding: 0px;"><span size="4" style="margin: 0px; padding: 0px; font-size: medium;"><span style="margin: 0px; padding: 0px; text-decoration: underline;">SYNd</span></span></strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">   在三ơ握手过E中Q服务器发送SYN-ACK之后Q收到客L的ACK之前的TCPq接UCؓ半连?half-open connect).此时服务器处于Syn_RECV状?当收到ACK后,服务器{入ESTABLISHED状?</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">  Synd是 d客户?在短旉内伪造大量不存在的IP地址Q向服务器不断地发送syn包,服务器回复确认包Qƈ{待客户的确认,׃源地址是不存在的,服务器需要不断的重发?臌Ӟq些伪造的SYN包将长时间占用未q接队列Q正常的SYNh被丢弃,目标pȝq行~慢Q严重者引Ll堵塞甚至系l瘫痪?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> Synd是一个典型的DDOSd。检SYNd非常的方便,当你在服务器上看到大量的半连接状态时Q特别是源IP地址是随机的Q基本上可以断定q是一ơSYNd.在Linux下可以如下命令检是否被Synd</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><strong style="margin: 0px; padding: 0px;">netstat -n -p TCP | grep SYN_RECV</strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">一般较新的TCP/IP协议栈都对这一q程q行修正来防范SyndQ修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半q接和羃短超时时间等.</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">但是不能完全防范synd?/p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><strong style="margin: 0px; padding: 0px;"><span style="margin: 0px; padding: 0px; text-decoration: underline;"><span size="4" style="margin: 0px; padding: 0px; font-size: medium;">TCP 四次挥手</span></span></strong></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">TCP的连接的拆除需要发送四个包Q因此称为四ơ挥?four-way handshake)。客L或服务器均可d发v挥手动作Q在socket~程中,M一Ҏ行close()操作卛_产生挥手操作?/p><div align="center" style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><img src="http://blogimg.chinaunix.net/blog/upfile2/100327022731.jpg" alt="" border="0" width="650" style="margin: 0px; padding: 0px; border: 0px;" /></div><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </p><div style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </div><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"> </p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">参见wireshark抓包Q实的抓包l果q没有严格按挥手时序。我估计是时间间隔太短造成?/p><div align="center" style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"><img src="http://blogimg.chinaunix.net/blog/upfile2/100327023334.png" alt="" border="0" width="650" style="margin: 0px; padding: 0px; border: 0px;" /></div><div align="center" style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;"></div><div align="center" style="margin: 0px; background-color: #ffffff; color: #494949; font-family: Arial, Helvetica, sans-serif; line-height: 22px;">source url:http://bluedrum.cublog.cn<br /><br /><br /><a target="_blank" style="text-decoration: none; color: #765f47; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;"><img src="http://s7.sinaimg.cn/middle/4d2c7ad6t937b6e58c1b6&690" real_src="http://s7.sinaimg.cn/middle/4d2c7ad6t937b6e58c1b6&690" width="501" height="632" alt="TCP状态变q图及状态说? title="TCP状态变q图及状态说? action-data="http%3A%2F%2Fs7.sinaimg.cn%2Fmiddle%2F4d2c7ad6t937b6e58c1b6%26690" action-type="show-slide" style="margin: 0px; padding: 0px; border: 0px; list-style: none;" /></a><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">状态:描述</span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">CLOSEDQ无q?/span><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">接是zd的或正在q行</span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">LISTENQ服务器在等待进入呼?/span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">SYN_RECVQ一个连接请求已l到达,{待认</span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">SYN_SENTQ应?/span><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">已经开始,打开一个连?/span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">ESTABLISHEDQ正常数</span><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">据传输状?/span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">FIN_WAIT1Q应用说它已l完?/span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">FIN_WAIT2Q另一边已同意释放</span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">ITMED_WAITQ等待所有分l死?/span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">CLOSINGQ两边同时尝试关?/span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">TIME_WAITQ另一边已初始化一个释?/span><br style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;" /><span style="color: #464646; font-family: simsun; line-height: 21px; text-align: left; background-color: #f8ecd8;">LAST_ACKQ等待所有分l死?/span></div><img src ="http://www.aygfsteel.com/xiaomage234/aggbug/400910.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/xiaomage234/" target="_blank">马?/a> 2013-06-24 16:33 <a href="http://www.aygfsteel.com/xiaomage234/archive/2013/06/24/400910.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux配置支持高ƈ发TCPq接(socket最大连接数) 【{?/title><link>http://www.aygfsteel.com/xiaomage234/archive/2012/03/26/372697.html</link><dc:creator>马?/dc:creator><author>马?/author><pubDate>Mon, 26 Mar 2012 03:49:00 GMT</pubDate><guid>http://www.aygfsteel.com/xiaomage234/archive/2012/03/26/372697.html</guid><wfw:comment>http://www.aygfsteel.com/xiaomage234/comments/372697.html</wfw:comment><comments>http://www.aygfsteel.com/xiaomage234/archive/2012/03/26/372697.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/xiaomage234/comments/commentRss/372697.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/xiaomage234/services/trackbacks/372697.html</trackback:ping><description><![CDATA[<p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #6d6d6d; line-height: 26px; font-family: arial; font-size: 12px; background-color: #ffffff; ">Linux配置支持高ƈ发TCPq接(socket最大连接数)及优化内核参?nbsp; </p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 1em; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #6d6d6d; line-height: 26px; font-family: arial; font-size: 12px; background-color: #ffffff; ">2011-08-09 15:20:58|  分类Q?a title="LNMP&&LAMP" style="color: #1463c4; ">LNMP&&LAMP</a>|  标签Q?a style="color: #1463c4; ">内核调优</a>  <a style="color: #1463c4; ">文gpȝ调优</a>  <a style="color: #1463c4; ">高ƈ发调?/a>  <a style="color: #1463c4; ">socketq接</a>  <a style="color: #1463c4; ">ip_conntract</a>  |字号大中?nbsp;<a style="color: #1463c4; ">订阅</a></p><div style="word-wrap: break-word; color: #9a9a9a; font-family: arial; font-size: 12px; line-height: 18px; background-color: #ffffff; "></div><div style="word-wrap: break-word; color: #9a9a9a; font-family: arial; font-size: 12px; line-height: 18px; background-color: #ffffff; "></div><div style="word-wrap: break-word; color: #9a9a9a; font-family: arial; font-size: 12px; line-height: 18px; background-color: #ffffff; "><div style="word-wrap: break-word; ">Linux配置支持高ƈ发TCPq接(socket最大连接数)</div>1、修改用戯E可打开文g数限?br />在Linuxq_上,无论~写客户端程序还是服务端E序Q在q行高ƈ发TCPq接处理Ӟ最高的q发数量都要受到pȝ对用户单一q程同时可打开文g数量的限?q是因ؓpȝ为每个TCPq接都要创徏一个socket句柄Q每个socket句柄同时也是一个文件句?。可使用ulimit命o查看pȝ允许当前用户q程打开的文件数限制Q?br />[speng@as4 ~]$ ulimit -n<br />1024<br />q表C当前用L每个q程最多允许同时打开1024个文Ӟq?024个文件中q得除去每个q程必然打开的标准输入,标准输出Q标准错误,服务器监?socketQ进E间通讯的unix域socket{文Ӟ那么剩下的可用于客户端socketq接的文件数只有大?024-10=1014个左叟뀂也是说缺省情况下Q基于Linux的通讯E序最多允许同?014个TCPq发q接?br />对于x持更高数量的TCPq发q接的通讯处理E序Q就必须修改Linux对当前用Lq程同时打开的文件数量的软限?soft limit)和硬限制(hardlimit)。其中Y限制是指Linux在当前系l能够承受的范围内进一步限制用户同时打开的文件数Q硬限制则是Ҏpȝg资源状况(主要是系l内?计算出来的系l最多可同时打开的文件数量。通常软限制小于或{于限制?br />修改上述限制的最单的办法是使用ulimit命oQ?br />[speng@as4 ~]$ ulimit -n <br />上述命o中,在中指定要设|的单一q程允许打开的最大文件数。如果系l回昄g“Operation notpermitted”之类的话Q说明上q限制修改失败,实际上是因ؓ在中指定的数Dq了Linuxpȝ对该用户打开文g数的软限制或限制。因此,需要修改Linuxpȝ对用L关于打开文g数的软限制和限制?br />W一步,修改/etc/security/limits.conf文gQ在文g中添加如下行Q?br />speng soft nofile 10240<br />speng hard nofile 10240<br />其中speng指定了要修改哪个用户的打开文g数限Ӟ可用'*'可CZҎ有用L限制Qsoft或hard指定要修改Y限制q是限Ӟ10240则指定了惌修改的新的限制|x大打开文g?h意Y限制D于或等于硬限制)。修改完后保存文件?br />W二步,修改/etc/pam.d/login文gQ在文g中添加如下行Q?br />session required /lib/security/pam_limits.so<br />q是告诉Linux在用户完成系l登录后Q应该调用pam_limits.so模块来设|系l对该用户可使用的各U资源数量的最大限?包括用户可打开的最大文件数限制)Q而pam_limits.so模块׃?etc/security/limits.conf文g中读取配|来讄q些限制倹{修改完后保存此文g?br />W三步,查看LinuxpȝU的最大打开文g数限Ӟ使用如下命oQ?br />[speng@as4 ~]$ cat /proc/sys/fs/file-max<br />12158<br />q表明这台Linuxpȝ最多允许同时打开(卛_含所有用h开文g数d)12158个文Ӟ是LinuxpȝU硬限制Q所有用L的打开文g数限刉不应过q个数倹{通常q个pȝU硬限制是Linuxpȝ在启动时Ҏpȝg资源状况计算出来的最佳的最大同时打开文g数限Ӟ如果没有Ҏ需要,不应该修Ҏ限制Q除非想为用L打开文g数限制设|超q此限制的倹{修Ҏ限制的Ҏ是修?etc/rc.local脚本Q在脚本中添加如下行Q?br />echo 22158 > /proc/sys/fs/file-max<br />q是让Linux在启动完成后系l打开文g数硬限制讄?2158。修改完后保存此文g?br />完成上述步骤后重启系l,一般情况下可以将LinuxpȝҎ定用L单一q程允许同时打开的最大文件数限制设ؓ指定的数倹{如果重启后?ulimit-n命o查看用户可打开文g数限制仍然低于上q步骤中讄的最大|q可能是因ؓ在用L录脚?etc/profile中用ulimit -n命o已经用户可同时打开的文件数做了限制。由于通过ulimit-n修改pȝ对用户可同时打开文g的最大数限制ӞC改的值只能小于或{于上次 ulimit-n讄的|因此想用此命令增大这个限制值是不可能的。所以,如果有上q问题存在,只能去打开/etc/profile脚本文gQ在文g中查找是否用了ulimit-n限制了用户可同时打开的最大文件数量,如果扑ֈQ则删除q行命oQ或者将其设|的值改为合适的|然后保存文gQ用户退出ƈ重新dpȝ卛_?br />通过上述步骤Q就为支持高q发TCPq接处理的通讯处理E序解除关于打开文g数量斚w的系l限制?br />2、修改网l内核对TCPq接的有关限Ӟ参考对比下文?#8220;优化内核参数”Q?br />在Linux上编写支持高q发TCPq接的客L通讯处理E序Ӟ有时会发现尽已l解除了pȝ对用户同时打开文g数的限制Q但仍会出现q发TCPq接数增加到一定数量时Q再也无法成功徏立新的TCPq接的现象。出现这U现在的原因有多U?br />W一U原因可能是因ؓLinux|络内核Ҏ地端口号范围有限制。此Ӟq一步分析ؓ什么无法徏立TCPq接Q会发现问题出在connect()调用q回p|Q查看系l错误提C消息是“Can't assign requestedaddress”。同Ӟ如果在此时用tcpdump工具监视|络Q会发现Ҏ没有TCPq接时客L发SYN包的|络量。这些情况说明问题在于本地Linuxpȝ内核中有限制。其实,问题的根本原因在于Linux内核的TCP/IP协议实现模块对系l中所有的客户端TCPq接对应的本地端口号的范围进行了限制(例如Q内栔R制本地端口号的范围ؓ1024~32768之间)。当pȝ中某一时刻同时存在太多的TCP客户端连接时Q由于每个TCP客户端连接都要占用一个唯一的本地端口号(此端口号在系l的本地端口可围限制中)Q如果现有的TCP客户端连接已所有的本地端口号占满,则此时就无法为新的TCP客户端连接分配一个本地端口号了,因此pȝ会在q种情况下在connect()调用中返回失败,q将错误提示消息设ؓ“Can't assignrequested address”。有兌些控刉辑可以查看Linux内核源代码,以linux2.6内核ZQ可以查看tcp_ipv4.c文g中如下函敎ͼ<br />static int tcp_v4_hash_connect(struct sock *sk)<br />h意上q函C对变量sysctl_local_port_range的访问控制。变量sysctl_local_port_range的初始化则是在tcp.c文g中的如下函数中设|:<br />void __init tcp_init(void)<br />内核~译旉认设|的本地端口可围可能太,因此需要修Ҏ本地端口范围限制?br />W一步,修改/etc/sysctl.conf文gQ在文g中添加如下行Q?br />net.ipv4.ip_local_port_range = 1024 65000<br />q表明将pȝҎ地端口范围限制设|ؓ1024~65000之间。请注意Q本地端口范围的最值必d于或{于1024Q而端口范围的最大值则应小于或{于65535。修改完后保存此文g?br />W二步,执行sysctl命oQ?br />[speng@as4 ~]$ sysctl -p<br />如果pȝ没有错误提示Q就表明新的本地端口范围讄成功。如果按上述端口范围q行讄Q则理论上单独一个进E最多可以同时徏?0000多个TCP客户端连接?br />W二U无法徏立TCPq接的原因可能是因ؓLinux|络内核的IP_TABLE防火墙对最大跟t的TCPq接数有限制。此时程序会表现为在 connect()调用中阻塞,如同LQ如果用tcpdump工具监视|络Q也会发现根本没有TCPq接时客L发SYN包的|络量。由?IP_TABLE防火墙在内核中会Ҏ个TCPq接的状态进行跟t,跟踪信息会攑֜位于内核内存中的conntrackdatabase中,q个数据库的大小有限Q当pȝ中存在过多的TCPq接Ӟ数据库容量不IIP_TABLE无法为新的TCPq接建立跟踪信息Q于是表Cؓ在connect()调用中阻塞。此时就必须修改内核Ҏ大跟t的TCPq接数的限制Q方法同修改内核Ҏ地端口号范围的限制是cM的:<br />W一步,修改/etc/sysctl.conf文gQ在文g中添加如下行Q?br />net.ipv4.ip_conntrack_max = 10240<br />q表明将pȝҎ大跟t的TCPq接数限制设|ؓ10240。请注意Q此限制D量,以节省对内核内存的占用?br />W二步,执行sysctl命oQ?br />[speng@as4 ~]$ sysctl -p<br />如果pȝ没有错误提示Q就表明pȝҎ的最大跟t的TCPq接数限制修Ҏ功。如果按上述参数q行讄Q则理论上单独一个进E最多可以同时徏?0000多个TCP客户端连接?br />3、用支持高q发|络I/O的编E技?br />在Linux上编写高q发TCPq接应用E序Ӟ必须使用合适的|络I/O技术和I/O事g分派机制?br />可用的I/O技术有同步I/OQ非d式同步I/O(也称反应式I/O)Q以及异步I/O。在高TCPq发的情形下Q如果用同步I/OQ这会严重阻塞程序的q{Q除非ؓ每个TCPq接的I/O创徏一个线E。但是,q多的线E又会因pȝ对线E的调度造成巨大开销。因此,在高TCPq发的情形下使用同步 I/O是不可取的,q时可以考虑使用非阻塞式同步I/O或异步I/O。非d式同步I/O的技术包括用select()Qpoll()Qepoll{机制。异步I/O的技术就是用AIO?br />从I/O事g分派机制来看Q用select()是不合适的Q因为它所支持的ƈ发连接数有限(通常?024个以?。如果考虑性能Qpoll()也是不合适的Q尽它可以支持的较高的TCPq发敎ͼ但是׃光?#8220;轮询”机制Q当q发数较高时Q其q行效率相当低,q可能存在I/O事g分派不均Q导致部分TCPq接上的I/O出现“饥饿”现象。而如果用epoll或AIOQ则没有上述问题(早期Linux内核的AIO技术实现是通过在内怸为每?I/Oh创徏一个线E来实现的,q种实现机制在高q发TCPq接的情形下使用其实也有严重的性能问题。但在最新的Linux内核中,AIO的实现已l得到改q??br />lg所qͼ在开发支持高q发TCPq接的Linux应用E序Ӟ应尽量用epoll或AIO技术来实现q发的TCPq接上的I/O控制Q这ؓ提升E序寚wq发TCPq接的支持提供有效的I/O保证?/div><img src ="http://www.aygfsteel.com/xiaomage234/aggbug/372697.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/xiaomage234/" target="_blank">马?/a> 2012-03-26 11:49 <a href="http://www.aygfsteel.com/xiaomage234/archive/2012/03/26/372697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SYN_RECV http://www.aygfsteel.com/xiaomage234/archive/2011/09/06/358119.html马?/dc:creator>马?/author>Tue, 06 Sep 2011 08:26:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2011/09/06/358119.htmlhttp://www.aygfsteel.com/xiaomage234/comments/358119.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2011/09/06/358119.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/358119.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/358119.html

SYN_RECV概述

  TCP SYN Flood是一U常见,而且有效的远?q程)拒绝服务(Denial of Service)d方式Q它透过一定的操作破坏TCP三次握手建立正常q接Q占用ƈ耗费pȝ资源Q得提供TCP服务的主机系l无法正常工作。由于TCP SYN Flood是透过|\底层Ҏ务器Serverq行d的,它可以在L改变自己的网路IP地址的同Ӟ不被|\上的其他讑֤所识别Q这样就l防范网路犯|部门追查犯|来源造成很大的困难。在国内内外的网站中Q这U攻d见不鲜。在一个拍卖网站上Q曾l有犯罪分子利用q种手段Q在低h位时L其他用户l箋对商品拍卖,q扰拍卖q程的正常运作?div style="height: 30px; line-height: 30px; overflow-x: hidden; overflow-y: hidden; ">

~辑本段如何判断

  一般情况下Q可以一些简单步骤进行检查,来判断系l是否正在遭受TCP SYN Floodd?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  1?服务端无法提供正常的TCP服务。连接请求被拒绝或超时?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  2、透过 netstat -an 命o查系l,发现有大量的SYN_RECVq接状态?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  查服务器链接QSYN_RECV状态最高时?00多个Q访问服务器|页特别慢,甚至时Q所以基本判定是SYN_RECVd?div style="height: 30px; line-height: 30px; overflow-x: hidden; overflow-y: hidden; ">

~辑本段解决Ҏ

  q个d的解x法如下:
  1Q增加未完成q接队列Qq0)的最大长度?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  echo 1280&gt;/proc/sys/net/ipv4/tcp_max_syn_backlog
  2, 启动SYN_cookie?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  echo 1&gt;/proc/sys/net/ipv4/tcp_syncookies
  q些是被动的ҎQ治标不L。而且加大了服务器的负担,但是可以避免被拒l攻击(只是减缓Q?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  L的方法是在防火墙上做手脚。但是现在能在一定程度上防住syn floodd的防火墙都不便宜。ƈ且把q个命o加入"/etc/rc.d/rc.local"文g?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  如果?/proc/sys/net/ipv4 下的配置文gq行解释Q可以参?LinuxAid技术站的文章。查看本文全文也可以参阅?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  关于 syn cookiesQ?请参?&lt;&gt; http://cr.yp.to/syncookies.html
  也许 使用mod_limitipconn.c来限制apache的ƈ发数 也会有一定的帮助?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  2. iptables的设|,引用自CU
  防止同步包洪_Sync FloodQ?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  # iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT
  也有人写?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  #iptables -A INPUT -p tcp --syn -m limit --limit 1/s -j ACCEPT
  --limit 1/s 限制synq发数每U?ơ,可以Ҏ自己的需要修?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  防止各种端口扫描
  # iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT
  Pingz水dQPing of DeathQ?div style="height: 14px; line-height: 14px; font-size: 12px; overflow-x: hidden; overflow-y: hidden; ">  # iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT




]]>
转老外一NGINX 防DDOS配置http://www.aygfsteel.com/xiaomage234/archive/2011/09/06/358120.html马?/dc:creator>马?/author>Tue, 06 Sep 2011 08:26:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2011/09/06/358120.htmlhttp://www.aygfsteel.com/xiaomage234/comments/358120.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2011/09/06/358120.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/358120.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/358120.html

标签Qnginx ddos d
 FreeBSD, network card: Intel fxp, port: 100Мбит, polling, http accept-filter.
in sysctl:
sysctl kern.maxfiles=90000
           sysctl kern.maxfilesperproc=80000
           sysctl net.inet.tcp.blackhole=2
           sysctl net.inet.udp.blackhole=1
           sysctl kern.polling.burst_max=1000
           sysctl kern.polling.each_burst=50
           sysctl kern.ipc.somaxconn=32768
           sysctl net.inet.tcp.msl=3000
           sysctl net.inet.tcp.maxtcptw=40960
           sysctl net.inet.tcp.nolocaltimewait=1
           sysctl net.inet.ip.portrange.first=1024
           sysctl net.inet.ip.portrange.last=65535
           sysctl net.inet.ip.portrange.randomized=0
in nginx configuration:
  worker_processes 1;
           worker_rlimit_nofile 80000;
           events {
               worker_connections 50000;
           }

           server_tokens off;
           log_format IP `$remote_addr';
           reset_timedout_connection on;

           listen  xx.xx.xx.xx:80  default rcvbuf=8192 sndbuf=16384 backlog=32000 accept_filter=httpready;
 
In the following way it is possible to realize filtration of url, in example for POST
index.php?action=login which is with empty referral.
   set $add 1;
           location /index.php {
                   limit_except GET POST {
                        deny all;
               }
               set $ban "";
               if ($http_referer = "" ) {set $ban $ban$add;}
               if ($request_method = POST ) {set $ban $ban$add;}
               if ($query_string = "action=login" ){set $ban $ban$add;}
               if ($ban = 111 ) {
                   access_log /var/log/[133]nginx/ban IP;
                   return 404;
               }
               proxy_pass http://127.0.0.1:8000; #here is a patch
           }
 
Further we cut it at pf level – loaded into IP table, hosts from which came too many hits.
PF with tables works very quickly. Sources for parsing of logs (ddetect) you can find on http://www.comsys.com.ua/files
Then Cron used once in a minute, to add into ip tables new IPs from a log.
25 Mbyte DDoS, which cuts IPs, the rests fall on nginx which by it is criterion pass IPs and the rests passed on the apache – LA 0, site works.



]]>
Cookieƺ骗 腾讯拍拍U杀zd的验证码漏洞http://www.aygfsteel.com/xiaomage234/archive/2011/08/16/356653.html马?/dc:creator>马?/author>Tue, 16 Aug 2011 11:30:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2011/08/16/356653.htmlhttp://www.aygfsteel.com/xiaomage234/comments/356653.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2011/08/16/356653.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/356653.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/356653.html
2010-12-05 19:36 zetsin newbyter.com 我要评论(2) 字号Q?span style="font-family: arial; font-weight: bold; font-size: 14px; ">T | T
一键收藏,随时查看Q分享好友!

有谁q记得大概几q前H然出现了验证码q东西,许多|站甚至桌面应用E序都陆l实C验证码技术,主要作用无非是防止用户利用E序q行自动提交Q避免暴力破解,避免服务器遭受恶意攻凅R?/p>

ADQ?/p>

首先我想讨论一下验证码q玩意儿?/p>

有谁q记得大概几q前H然出现了验证码q东西,许多|站甚至桌面应用E序都陆l实C验证码技术,主要作用无非是防止用户利用E序q行自动提交Q避免暴力破解,避免服务器遭受恶意攻凅R?/p>

那么Q验证码机制又该如何实现?/p>

目前L的实现技术主要有session和cookie两种方式Q而这两种方式可以说技术是一LQ区别在于将验证码字W串存储在服务器q是客户端?/p>

前者工作流E:服务器发送验证码囄到客Lq在服务器保存验证码字符串到sessionQ用戯L认图片ƈ提交验证码字W串到服务器Q服务器用h交的验证码字W串与session中保存的字符串进行比较?/p>

后者工作流E:服务器发送验证码囄以及验证码字W串Q可能会q行加密Q到客户端,客户端将验证码字W串存储到本地cookieQ用戯L认图片ƈ提交验证码字W串以及cookie中所存储的字W串到服务器Q服务器用h交的两个字符Ԍq行解密后)q行比较?/p>

相对而言Q存攑֜服务器的session更ؓ安全Q只不过消耗服务器内存Q程序员除了使用模式识别辨认出验证码Q没有其他办法。而对于用cookie方式的验证码Q不增加服务器内存消耗,但我们可以通过对传输数据进行分析轻易破解验证码?/p>

q种传统的验证码方式Q其框架非常单?/p>

  

看上图,我们从大的框架分析问题,q里面说?#8220;提供验证码服?#8221;已经不区分sessionq是cookie了?/p>

接下来从图中我们可以看出什么了呢,对于有多台服务器的大企业是十分^常的Q那么,假如每一个服务程序都使用验证码技术,那么每一个服务程序就需要独自实现验证码服务Q这样做不是不可以,只是增加了程序员的负担而已?/p>

好吧Q现在我们正式进入今天的主题Q也是接着上面的话题,腾讯的验证码框架有何不同?/p>

我们随便q入一个需要验证码的腾讯页面:

http://web2.qq.com

dwebQQ的时候需要输入验证码Q我们通过抓包或者看源代码,可以知道点击“换一?#8221;时其实是讉K了这个URLQhttp://captcha.qq.com/getimageQ来自tencent http server。多试几个需要验证码的页面,发现光证码依然是是通过讉Khttp://captcha.qq.com/getimage获得。当然也有例外的情况Q不qM看来腾讯的验证码机制的框架与上面讨论的又有些不一栗?/p>

看到了吗Q在q种框架体系下,验证码成了一个单独的lgQ不同服务器不同应用E序都可使用它提供的验证码服务接口?/p>

具体程

好吧Q我们l进一步研I腾讯验证码的具体流E?/p>

讉Khttp://captcha.qq.com/getimageQ看?#8220;zqcu”验证码图片,抓包Q查看响应标_

??/p>

响应 HTTP/1.1 200 OK

Server tencent http server

Accept-Ranges bytes

Pragma No-cache

Content-Length 2559

Set-Cookie verifysession=h0052f5e46e7ca7d3f1bbb1cfa3bbb2a9ea86bded65adbf78e575c50e0d361145fcd232015653790eb

4;PATH=/; DOMAIN=qq.com;

Connection close

Content-Type image/jpeg

以上是HTTP协议中的header内容Q请注意其中Set-Cookie的部分,其实q就是验证码“zqcu”字符串经q加密后的密文。当我们提交验证码时Q正是将我们输入?#8220;zqcu”和密文同时提交,然后服务器A/B再通过服务器C的验证接口判断是否正。这时候,一切Q云都是神马了Q原来腾讯验证码居然采用cookie方式?/p>

那么Q接下来高手通常会有两种做法Q?/p>

W一Q通过模式识别辨认出图片所承蝲的验证码字符Ԍ然后提交的时候直接发送识别的字符丌Ӏ?/p>

W二Q通过解密破译出verifysession的明文?/p>

很抱歉,我不是高手,以上两种Ҏ我都无能为力。所以,以下的内定w手可l过Q到此结束了?/p>

利用cookieƺ骗l过验证?/p>

到这里,有h可能会骂Q你q不是标题党么,什么cookieƺ骗Q什么漏z,啥都没?/p>

好吧Q接下来讲讲我的ҎQ就是利用cookieƺ骗l过验证码?/p>

刚才我们讉Khttp://captcha.qq.com/getimage的时候已l获得一个验证码囄Q利用hD别技术,知道它的验证码字W串?#8220;zqcu”Qƈ且截获了其密文verifysession?/p>

于是Q我便开始尝试每ơ提交都提交“zqcu”q且cookie设ؓ已知的verifysession。嘿嘿,我可以把入哥的介l信多复印好几䆾嘛?/p>

如果真的那么单的话,腾讯也太二了?/p>

W一ơ提交的时候,我十分惊喜,居然成功ƺ骗了服务器?/p>

可是当我再次使用q一l验证码及其密文Q却q回验证码错误的提示。我的猜xQ某个验证码用过之后Q不能马上再ơ用,也许要过1分钟或?个小时之后才能用,q是一个我UC期机制的坎。也是_当洪哥问入哥Q这是你写的介绍信么Q入哥看了看Q说是,然后l这信M一个标志?/p>

发现了这个坎Q那么悲剧了?/p>

现在我能做的事只有:提前获得几组甚至几百几千l验证码Q需要hD别,人手输入Q及其密文。而且所获得的验证码q不能闲|太长时_入哥可能同一份介l信发给两个人,当别人先用了它,那么我要q一D|间才能再用?/p>

注意上面提到了提前两字,但是同样需要h工识别ƈ输入Q这到底有什么用呢?/p>

在做什么事情的时候我们是带着q样一个目的的Q提前输入好几组验证码,在特定时间连lƈ快速的提交?/p>

好吧Q我不多说了Q看看标题,我们开始暴力秒杀吧?/p>

拍拍U杀程如下Q商品有一个秒杀旉Q当Cq个旉Q成千上万的玩家开始填写验证码q点L交,先到先得?/p>

于是Q有了cookieƺ骗Q我可以提前输入验证码,当时间一刎ͼ只要提交卛_?/p>

今天p到这里吧Q大家可以畅所Ʋ言Q提出疑问或者指出错误的地方。最后附上我做的拍拍U杀助手Qؓ了图个方便用的c#~程Q所以需?net farmework环境Q有兴趣的同学可以将其改写成c++?/p>

PSQ修Ҏ地cookie非常单,但是Q腾讯这里的Set-Cookieq不是保存到本地的cookieQ它是一个标志ؓhttponly的cookieQ只存储在标头?/p>

我提供一个函敎ͼInternetSetCookieEx()Q其msdn如下Q?/p>

http://msdn.microsoft.com/zh-cn/library/aa385108.aspx

附下载链接:http://d.namipan.com/d/efb4375ee41afae5932279334313c00442c995d2ee600800



]]>
谈一谈网l编E学习经?/title><link>http://www.aygfsteel.com/xiaomage234/archive/2011/06/09/352000.html</link><dc:creator>马?/dc:creator><author>马?/author><pubDate>Thu, 09 Jun 2011 09:16:00 GMT</pubDate><guid>http://www.aygfsteel.com/xiaomage234/archive/2011/06/09/352000.html</guid><wfw:comment>http://www.aygfsteel.com/xiaomage234/comments/352000.html</wfw:comment><comments>http://www.aygfsteel.com/xiaomage234/archive/2011/06/09/352000.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/xiaomage234/comments/commentRss/352000.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/xiaomage234/services/trackbacks/352000.html</trackback:ping><description><![CDATA[<span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 18px; "><div><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">谈一谈网l编E学习经?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">陈硕</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">giantchen@gmail.com</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">blog.csdn.net/Solstice</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">2011-06-08</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">PDF 版下载:<a title="https://github.com/downloads/chenshuo/documents/LearningNetworkProgramming.pdf" style="color: #0066aa; text-decoration: none; ">https://github.com/downloads/chenshuo/documents/LearningNetworkProgramming.pdf</a></p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">本文谈一谈我在学习网l编E方面的一些个人经验?#8220;|络~程”q个术语的范围很q,本文指用Sockets API开发基于TCP/IP的网l应用程序,具体定义?#8220;|络~程的各UQ务角?#8221;一节?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">受限于本人的l历和经验,q篇文章的适应范围是:</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· x86-64 Linux服务端网l编E,直接或间接?Sockets API</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 公司内网。不一定是局域网Q但M位于公司防火墙之内,环境可控</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">本文可能不适合Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· PC客户端网l编E,E序q行在客LPC上,环境多变且不可控</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· Windows|络~程</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 面向公网的服务程?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 高性能|络服务?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">本文分两个部分:</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">1. |络~程的一些胡思ؕ惻I谈谈我对q一领域的认?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">2. 几本必看的书Q基本上q是W. Richard Stevents那几?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">另外Q本文没有特别说明时均暗指TCP协议Q?#8220;q接”?#8220;TCPq接”Q?#8220;服务?#8221;?#8220;TCP服务?#8221;?/p><h3>|络~程的一些胡思ؕ?/h3><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">以下胡ؕ列出我对|络~程的一些想法,前后无关联?/p><h4>|络~程是什么?</h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">|络~程是什么?是熟l用Sockets API吗?说实话,在实际项目里我只用过两次Sockets APIQ其他时候都是用封装好的网l库?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">W一ơ是2005q在学校做一个羽毛球赛场计分pȝQ我用C# ~写q行在PCZ的YӞ负责比分的显C;再用C# 写了q行在PDA上的计分界面Q记分员拿着PDA记录比分Q这两部分程序通过 TCP协议怺通信。这其实是个单的分布式系l,体育馆有不止一片场圎ͼ每个场地都有一名拿PDA的记分员Q每个场地都有两台显C比分的PC机(昄器是42吋^板电视,攑֜场地的对角,q样两边看台的观众都能看到比分)。这两台PC机功能不完全一P一台只负责昄当前比分Q另一台还要负责与PDA通信Qƈ更新数据库里的比分信息。此外,q有一台PC责周期性地从数据库d全部7片场地的比分Q显C在体育馆墙上的大屏q上。这台PC上还q行着一个程序,负责生成比分数据的静态页面,通过FTP上传发布到某门户|站的体育频道。系l中q有一个录入赛E(参赛队,q动员,出场序{)数据库的E序Q运行在数据库服务器上。算下来整个pȝ有十来个E序Q运行在二十多台讑֤QPC和PDAQ上Q还要考虑可靠性。将来有Z把这个小pȝ仔细讲一Ԍ挺有意思的?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q是我第一ơ写实际目中的|络E序Q当时写下来的感觉是像写命o行与用户交互的程序:E序在命令行输出一句提CQ等待客戯入一句话Q然后处理客戯入,再输Z一句提CQ如此@环。只不过q里?#8220;客户”不是人,而是另一个程序。在建立好TCPq接之后Q双方的E序都是read/write循环Qؓ求简单,我用的是blockingdQ,直到有一Ҏ开q接?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">W二ơ是2010q编写muduo|络库,我再ơ拿起了Sockets APIQ写了一个基于Reactor模式的C++ |络库。写q个库的目的之一是惌日常的网l编E从Sockets API的琐细节中解脱出来Q让E序员专注于业务逻辑Q把旉用在刀刃上。Muduo |络库的CZ代码包含了几十个|络E序Q这些示例程序都没有直接使用Sockets API?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">在此之外Q无论是实习q是工作Q虽然我写的E序都会通过TCP协议与其他程序打交道Q但我没有直接用过Sockets API。对于TCP|络~程Q我认ؓ核心是处?#8220;三个半事?#8221;Q见《Muduo |络~程CZ之零Q前a》中?#8220;TCP |络~程本质?#8221;。程序员的主要工作是在事件处理函C实现业务逻辑Q而不是和Sockets API较劲?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q里q是没有说清?#8220;|络~程”是什么,Ll阅d?#8220;|络~程的各UQ务角?#8221;?/p><h4>学习|络~程有用吗?</h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">以上说的是比较底层的|络~程Q程序代码直接面对从TCP或UDP收到的数据以及构造数据包发出厅R在实际工作中,另一U常?的情冉|通过各种 client library 来与服务端打交道Q或者在现成的框架中填空来实现serverQ或者采用更上层的通信方式。比如用libmemcached与memcached打交道,使用libpq来与PostgreSQL 打交道,~写Servlet来响应httphQ用某URPC与其他进E通信Q等{。这些情况都会发生网l通信Q但不一定算?#8220;|络~程”。如果你的工作是前面列D的这些,学习TCP/IP|络~程q有用吗Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">我认是有必要学一学,臛_在troubleshooting 的时候有用。无论如何,q些library或framework都会调用底层的Sockets API来实现网l功能。当你的E序遇到一个线上问题,如果你熟悉Sockets APIQ那么从strace不难发现E序卡在哪里Q尽可能你没有直接调用q些Sockets API。另外,熟悉TCP/IP协议、会用tcpdump也大大有助于分析解决U上|络服务问题?/p><h4>在什么^C学习|络~程Q?/h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">对于服务端网l编E,我徏议在Linux上学习?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">如果?0q前Q这个问题的{案或许是FreeBSDQ因为FreeBSDҎ苗红Q在2000q那一ơ互联网潮中扮演了重要角色Q是很多公司首选的免费服务器操作系l?000q那会儿Linuxq远未成熟,qepoll都还没有实现。(FreeBSD?001q发?.1版,加入了kqueueQ从此C10k不是问题。)</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">10q后的今天,事情起了变化QLinux成ؓ了市Z额最大的服务器操作系l?http://en.wikipedia.org/wiki/Usage_share_of_operating_systems)。在Linuxq种大众pȝ上学|络~程Q遇C么问题会比较Ҏ解决。因为用的h多,你遇到的问题别h多半也遇到过Q同样因为用的h多,如果真的有什么内核bugQ很快就会得C复,臛_有work around的办法。如果用别的pȝQ可能一个问题发到论坛上半个月都不会有h理。从内核源码的风格看QFreeBSD更干净整洁Q注释到位,但是无奈它的市场份额q不如LinuxQ学习Linux是更好的技术投资?/p><h4>可移植性重要吗Q?/h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">写网l程序要不要考虑UL性?q取决于目需要,如果贵公司做的程序要卖给其他公司Q而对方可能用Windows、Linux、FreeBSD、Solaris、AIX、HP-UX{等操作pȝQ这时候考虑UL性。如果编写公司内部的服务器上用的|络E序Q那么大可只x一个^収ͼ比如Linux。因为编写和l护可移植的|络E序的代L当高Q^台间的差异可能远比想象中大,即便是POSIXpȝ之间也有不小的差异(比如Linux没有SO_NOSIGPIPE选项Q,错误的返回码也大不一栗?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">我就不打把muduo往Windows或其他操作系l移植。如果需要编写可UL的网l程序,我宁愿用libevent或者Java Nettyq样现成的库Q把脏活累活留给别h?/p><h4>|络~程的各UQ务角?/h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">计算机网l是?big topicQ涉及很多h物和角色Q既有开发h员,也有q维人员。比方说Q公司内部两台机器之?ping 不通,通常ql运lh员解冻I看看是布U有问题q是路由器设|不对;两台机器能ping通,但是E序q不上,l检查是本机防火墙设|有问题Q通常ql管理员解决Q两台机器能q上Q但是丢包很严重Q发现是|卡或者交换机的网口故障,q件维修h员解冻I两台机器的程序能q上Q但是偶发q去的请求得不到响应Q通常是程序bugQ应该由开发h员解冟?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">本文主要兛_开发h员这一角色。下面简单列Z些我能想到的跟网l打交道的编EQ务,其中前三Ҏ面向|络本nQ后面几Ҏ在计机|络之上构徏信息pȝ?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">1. 开发网l设备,~写防火墙、交换机、\由器的固?firmware</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">2. 开发或UL|卡的驱?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">3. UL或维护TCP/IP协议栈(特别是在嵌入式系l上Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">4. 开发或l护标准的网l协议程序,HTTP、FTP、DNS、SMTP、POP3、NFS</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">5. 开发标准网l协议的“附加?#8221;Q比如HAProxy、squid、varnish{web load balancer</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">6. 开发标准或非标准网l服务的客户端库Q比如ZooKeeper客户端库Qmemcached客户端库</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">7. 开发与公司业务直接相关的网l服务程序,比如x聊天软g的后台服务器Q网游服务器Q金融交易系l,互联|企业用的分布式量存储Q微博发帖的内部q播通知Q等{?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">8. 客户端程序中涉及|络的部分,比如邮g客户端中?POP3、SMTP通信的部分,以及|游的客LE序中与服务器通信的部?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">本文所指的“|络~程”专指W?,卛_TCP/IP协议之上开发业务Y件?/p><h4>面向业务的网l编E的特点</h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">跟开发通用的网l程序不同,开发面向公怸务的专用|络E序有其特点Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 业务逻辑比较复杂Q而且时常变化</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">如果写一个HTTP服务器,在大致实现HTTP /1.1标准之后Q程序的M功能一般不会有太大的变化,E序员会把时间放在性能调优和bug修复上。而开发针对公怸务的专用E序Ӟ功能说明书(specQ很可能不如HTTP/1.1标准那么l致明确。更重要的是Q程序是快速演化的。以x聊天工具的后台服务器ZQ可能第一版只支持在线聊天Q几个月之后发布W二版,支持ȝ消息Q又q了几个月,W三版支持隐w聊天;随后Q第四版支持上传头像Q如此等{。这要求E序员能快速响应新的业务需求,公司才能保持竞争力?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 不一定需要遵循公认的通信协议标准</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">比方说网游服务器没什么协议标准,反正客户端和服务端都是本公司开发,如果发现目前的协议设计有问题Q两边一h了就是了?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· E序l构没有定论</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">对于高ƈ发大吞吐的标准网l服务,一般采用单U程事g驱动的方式开发,比如HAProxy、lighttpd{都是这个模式。但是对于专用的业务pȝQ其业务逻辑比较复杂Q占用较多的CPU资源Q这U单U程事g驱动方式不见得能发挥现在多核处理器的优势。这留给E序员比较大的自由发挥空_做好了横扫千军,做烂了一败涂地?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 性能评判的标准不?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">如果开发httpdq样的通用服务Q必然会和开源的Nginx、lighttpd{高性能服务器比较,E序员要投入相当的精力去优化E序Q才能在市场上占有一席之地。而面向业务的专用|络E序不一定有开源的实现以供Ҏ性能Q程序员通常更加注重功能的稳定性与开发的便捷性。性能只要一代比一代强卛_?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· |络~程起到支撑作用Q但不处于主导地?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">E序员的主要工作是实C务逻辑Q而不只是实现|络通信协议。这要求E序员深入理解业务。程序的性能瓉不一定在|络上,瓉有可能是CPU、Disk IO、数据库{等Q这时优化网l方面的代码q不能提高整体性能。只有对所在的领域有深入的了解Q明白各U因素的权衡(trade-off)Q才能做Z些有针对性的优化?/p><h4>几个术语</h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">互联|上的很多口水战是由对同一术语的不同理解引LQ比我写的《多U程服务器的适用场合》就曄说是“挂羊头卖狗肉”Q因文章中丄 master例子“Ҏq不上是个|络服务器。因为它的瓶颈根本就跟网l无兟?#8221;</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· |络服务?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">“|络服务?#8221;q个术语实含义模糊Q到底指gq是软gQ到底是服务于网l本w的机器Q交换机、\由器、防火墙、NATQ,q是利用|络为其他h或程序提供服务的机器Q打印服务器、文件服务器、邮件服务器Q。每个hҎ自己熟悉的领域,可能会有不同的解诅R比方说或许有h认ؓ只有支持高ƈ发高吞吐的才是|络服务器?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">Z避免无谓的争执,我只?#8220;|络服务E序”或?#8220;|络应用E序”q种含义明确的术语?#8220;开发网l服务程?#8221;通常不会造成误解?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 客户端?服务端?</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">在TCP|络~程里边Q客L和服务端很容易区分,d发vq接的是客户端,被动接受q接的是服务端。当Ӟq个“客户?#8221;本n也可能是个后台服务程序,HTTP Proxy对HTTP Server来说是个客L?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 客户端编E?服务端编E?</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">但是“服务端编E?#8221;?#8220;客户端编E?#8221;׃那么好区分。比?Web crawlerQ它会主动发起大量连接,扮演的是HTTP客户端的角色Q但g应该归入“服务端编E?#8221;。又比如写一?HTTP proxyQ它既会扮演服务?#8212;—被动接受 web browser 发v的连接,也会扮演客户?#8212;—d?HTTP server 发vq接Q它I竟服务端q是客户端?我猜大多Ch会把它归入服务端~程?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">那么I竟如何定义“服务端编E?#8221;Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">服务端编E需要处理大量ƈ发连接?也许是,也许不是。比如云风在一介l网游服务器的博?a style="color: #0066aa; text-decoration: none; ">http://blog.codingnow.com/2006/04/iocp_kqueue_epoll.html</a>中就谈到Q网怸用到?#8220;q接服务?#8221;需要处理大量连接,?#8220;逻辑服务?#8221;只有一个外部连接。那么开发这U网?#8220;逻辑服务?#8221;服务端~程q是客户端编E呢Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">我认为,“服务端网l编E?#8221;指的是编写没有用L面的长期q行的网l程序,E序默默地运行在一台服务器上,通过|络与其他程序打交道Q而不必和人打交道。与之对应的是客L|络E序Q要么是短时间运行,比如wgetQ要么是有用L面(无论是字W界面还是图形界面)。本文主要谈服务端网l编E?/p><h4>7x24重要吗?内存片可怕吗Q?/h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">一谈到服务端网l编E,有h立刻会提?x24q行的要求。对于某些网l设备而言Q这是合理的需求,比如交换机、\由器。对于开发商业系l,我认求程?x24q行通常是系l设计上考虑不周。具体见《分布式pȝ的工E化开发方法》第20v。重要的不是7x24Q而是在程序不必做?x24的情况下也能辑ֈ_高的可用性。一个考虑周到的系l应该允许每个进E都能随旉启,q样才能在廉L服务器硬件上做到高可用性?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">既然不要?x24Q那么也不必x内存碎片,理由如下Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 64-bitpȝ的地址I间_大,不会出现没有_的连l空间这U情c?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 现在的内存分配器Qmalloc及其W三方实玎ͼ今非昔比Q除了memcachedq种U以内存为卖点的E序需要自p计分配器之外Q其他网l程序大可用系l自带的malloc或者某个第三方实现?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· Linux Kernel也大量用C动态内存分配。既然操作系l内栔R不怕动态分配内存造成片Q应用程序ؓ什么要x?</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 内存片如何度量Q有没有什么工兯为当前进E的内存片状况评个分?如果不能比较两种Ҏ的内存碎片程度,谈何优化Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">有hZ避免内存片Q不使用STL容器Q也不敢new/deleteQ这是premature optimizationq是因噎废食呢?</p><h4>协议设计是网l编E的核心</h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">对于专用的业务系l,协议设计是核心Q务,军_了系l的开发难度与可靠性,但是q个领域q没有Ş成大家公认的设计程?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">pȝ中哪个程序发赯接,哪个E序接受q接Q如果写标准的网l服务,那么q不是问题,按RFC来就行了。自p计业务系l,有没有章法可循?以网ؓ例,到底是连接服务器dq接逻辑服务器,q是逻辑服务器主动连?#8220;q接服务?#8221;Q似乎没有定论,两种做法都行。一般可以按?#8220;依赖->被依?#8221;的关pL设计发vq接的方向?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">比新接难的是关闭q接。在传统的网l服务中Q特别是短连接服务)Q不是服务端主动关闭连接,比如daytime、HTTP/1.0。也有少部分是客Ld关闭q接Q通常是些长连接服务,比如 echo、chargen{。我们自q业务pȝ该如何设计连接关闭协议呢Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">服务端主动关闭连接的~点之一是会多占用服务器资源。服务端d关闭q接之后会进入TIME_WAIT状态,在一D|间之内hold住一些内核资源。如果ƈ发访问量很高Q这会媄响服务端的处理能力。这g暗示我们应该把协议设计ؓ客户端主动关闭,让TIME_WAIT状态分散到多台客户机器上,化整为零?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q又有另外的问题Q客L赖着不走怎么办?会不会造成拒绝服务dQ或许有一个二者结合的ҎQ客L在收到响应之后就应该d关闭Q这h TIME_WAIT 留在客户端。服务端有一个定时器Q如果客L若干U钟之内没有d断开Q就t掉它。这样善意的客户端会把TIME_WAIT留给自己Qbuggy的客L会把 TIME_WAIT留给服务端。或者干脆用长q接协议Q这样避免频J创建销毁连接?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">比连接的建立与断开更重要的是设计消息协议。消息格式很好办QXML、JSON、Protobuf都是很好的选择Q难的是消息内容。一个消息应该包含哪些内容?多个E序怺通信如何避免race conditionQ见《分布式pȝ的工E化开发方法》p.16的例子)Q系l的全局状态该如何跃迁Q可惜这斚w可供参考的例子不多Q也没有太多通用的指导原则,我知道的只有30q前提出的end-to-end principle和happens-before relationship。只能从实践中慢慢积累了?/p><h4>|络~程的三个层?/h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">侯捷先生在《O談程序員與編E》中讲到 STL q用的三个档ơ:“會用STLQ是一E檔ơ。對STL原理有所了解Q又是一個檔ơ。追y過STL源碼Q又是一個檔ơ。第三種檔次的h用v STL 來,虎虎生風之勢i非W一檔次的h能夠望其項背?#8221;</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">我认为网l编E也可以分ؓ三个层次Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">1. 读过教程和文?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">2. 熟悉本系lTCP/IP协议栈的脾气</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">3. 自己写过一个简单的TCP/IP stack</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">W一个层ơ是基本要求Q读q《Unix|络~程》这L~程教材Q读q《TCP/IP详解》基本理解TCP/IP协议Q读q本pȝ的manpage。这个层ơ可以编写一些基本的|络E序Q完成常见的d。但|络~程不是照猫画虎q么单,若是按照manpage的功能描q就能编写品的网l程序,那h生就太幸了?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">W二个层ơ,熟悉本系l的TCP/IP协议栈参数设|与优化是开发高性能|络E序的必备条件。摸透协议栈的脾气还能解军_作中遇到的比较复杂的|络问题。拿Linux的TCP/IP协议栈来_</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 有可能出现自q接Q见《学之者生Q用之者死——ACE历史与简评》D的三个硬伤)Q程序应该有所准备?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· Linux的内怼有bugQ比如某UTCP拥塞控制法曄出现TCP window clampingQ窗口箝位)bugQ导致吞吐量暴跌Q可以选用其他拥塞控制法来绕开(work around)q个问题?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q些阴暗角落在manpage里没有描qͼ要通过其他渠道了解?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">~写可靠的网l程序的关键是熟悉各U场景下的error codeQ文件描q符用完了如何?本地ephemeral port暂时用完Q不能发hq接怎么办?服务端新建ƈ发连接太快,backlog用完了,客户端connect会返回什么错误?Q,有的在manpage里有描述Q有的要通过实践或阅L码获得?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">W三个层ơ,通过自己写一个简单的TCP/IP协议栈,能大大加深对TCP/IP的理解,更能明白TCPZ么要q么设计Q有哪些因素制约Q每一步操作的代h是什么,写v|络E序来更是成竹在胸?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">其实实现TCP/IP只需要操作系l提供三个接口函敎ͼ一个函敎ͼ两个回调函数。分别是Qsend_packet()、on_receive_packet()、on_timer()。多q前有一文章《用libnet与libpcap构造TCP/IP协议软g》介l了在用h实现TCP/IP的方法。lwIP也是很好的借鉴对象?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">如果有时_我打自己写一个Mini/Tiny/Toy/Trivial/Yet-Another TCP/IP。我准备换一个思\Q用TUN/TAP讑֤在用h实C个能与本机点对点通信的TCP/IP协议栈,q样那三个接口函数就表现为我最熟悉的文件读写。在用户态实现的好处是便于调试,协议栈做成静态库Q与应用E序链接CP库的接口不必是标准的Sockets APIQ。做完这一版,q可以l发挥,用FTDI的USB-SPI接口芯片q接ENC28J60适配器,做一个真正独立于操作pȝ的TCP/IP stack。如果只实现最基本的IP、ICMP Echo、TCP的话Q代码应能控制在3000行以内;也可以实现UDPQ如果应用程序需要用到DNS的话?/p><h4>最主要的三个例?/h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">我认为TCP|络~程有三个例子最值得学习研究Q分别是echo、chat、proxyQ都是长q接协议?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">Echo的作用:熟悉服务端被动接受新q接、收发数据、被动处理连接断开。每个连接是独立服务的,q接之间没有兌。在消息内容斚wEcho有一些变U:比如做成一问一{的方式Q收到的h和发送响应的内容不一Pq时候要考虑打包与拆包格式的设计Q进一步还可以写简单的HTTP服务?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">Chat的作用:q接之间的数据有交流Q从a收到的数据要发给b。这样对q接理提出的更高的要求Q如何用一个程序同时处理多个连接?fork() per connectiong是不行的。如何防止串话?b有可能随时断开q接Q而新建立的连接c可能恰好复用了b的文件描q符Q那么a会不会错误地把消息发lcQ?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">Proxy的作用:q接的管理更加复杂:既要被动接受q接Q也要主动发赯接,既要d关闭q接Q也要被动关闭连接。还要考虑两边速度不匹配,见《Muduo |络~程CZ之十Qsocks4a 代理服务器》?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q三个例子功能简单,H出了TCP|络~程中的重点问题Q挨着做一遍基本就能达到层ơ一的要求?/p><h4>TCP的可靠性有多高Q?/h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">TCP?#8220;面向q接的、可靠的、字节流传输协议”Q这里的“可靠”I竟是什么意思?《Effective TCP/IP Programming》第9条说QRealize That TCP Is a Reliable Protocol, Not an Infallible ProtocolQ那么TCP在哪U情况下会出错?q里说的“出错”指的是收到的数据与发送的数据不一_而不是数据不可达?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">我在《一U自动反消息类型的 Google Protobuf |络传输Ҏ》中设计了带check sum的消息格式,很多CZ理解Q认为是多余的。IP header里边有check sumQTCP header也有check sumQ链路层以太|还有CRC32校验Q那么ؓ什么还需要在应用层做校验Q什么情况下TCP传送的数据会出错?</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">IP header和TCP header的check sum是一U非常弱?6-bit check sum法Q把数据当成反码表示?6-bit integersQ再加到一赗这Uchecksum法能检Z些简单的错误Q而对某些错误无能为力Q由于是单的加法Q遇?#8220;?#8221;不变的情况就无法查出错误Q比如交换两?6-bit整数Q加法满交换律Q结果不变)。以太网的CRC32只能保证同一个网D上的通信不会出错Q两台机器的|线插到同一个交换机上,q时候以太网的CRC是有用的Q。但是,如果两台机器之间l过了多U\由器呢?</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; "><img title="router" border="0" alt="router" src="http://www.cppblog.com/images/cppblog_com/Solstice/Windows-Live-Writer/958c781e7d58_E312/router_3.png" width="471" height="305" style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px; " /></p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">上图中Client向Server发了一个TCP segmentQ这个segment先被装成一个IP packetQ再被封装成ethernet frameQ发送到路由器(图中消息aQ。Router收到ethernet frame (b)Q{发到另一个网D?c)Q最后Server收到dQ通知应用E序。Ethernet CRC能保证a和b相同Qc和d相同QTCP header check sum的强度不以保证收发payload的内容一栗另外,如果把Router换成NATQ那么NAT自己会构造cQ替换掉源地址Q,q时候a和d的payload不能用tcp header checksum校验?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">路由器可能出现硬件故障,比方说它的内存故障(或偶焉误)D收发IP报文出现多bit的反转或双字节交换,q个反{如果发生在payload区,那么无法用链路层、网l层、传输层的check sum查出来,只能通过应用层的check sum来检。这个现象在开发的时候不会遇刎ͼ因ؓ开发用的几台机器很可能都连到同一个交换机Qethernet CRC能防止错误。开发和试的时候数据量不大Q错误很隑֏生。之后大规模部v到生产环境,|络环境复杂Q这时候出个错p人措手不及。有一论文《When the CRC and TCP checksum disagree》分析了q个问题。另外《The Limitations of the Ethernet CRC and TCP/IP checksums for error detection?<a style="color: #0066aa; text-decoration: none; ">http://noahdavids.org/self_published/CRC_and_checksum.html</a>)也值得一诅R?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q个情况真的会发生吗Q会的,Amazon S3 ?008q?月就遇到q,单bit反{D了一ơ严重线上事故,所以他们吸取教训加?check sum。见<a style="color: #0066aa; text-decoration: none; ">http://status.aws.amazon.com/s3-20080720.html</a></p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">另外一个例证:下蝲大文件的时候一般都会附上MD5Q这除了有安全方面的考虑Q防止篡改)Q也说明应用层应该自p法校验数据的正确性。这是end-to-end principle的一个例证?/p><h3>三本必看的书</h3><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">谈到Unix~程和网l编E,W. Richard Stevens 是个l不开的h物,他生前写?本书QAPUE、两卷UNP、三卷TCP/IP。有四本与网l编E直接相兟뀂UNPW二卷其实跟|络~程关系不大Q是APUE在多U程和进E间通信(IPC)斚w的补充。很多h把TCP/IP一二三卷作为整体推荐,其实q三本书用处不同Q应该区别对待?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q里谈到的几本书都没有超出孟岩在《TCP/IP |络~程之四书五l》中的推荐,说明|络~程q一领域已经相对成熟E_?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· ?em>TCP/IP Illustrated</em>, <em>Vol. 1: The Protocols</em>》中文名《TCP/IP 详解》,以下U?TCPv1?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">TCPv1 是一本奇书?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q本书迄今至被三百多篇学术论文引用q?a style="color: #0066aa; text-decoration: none; ">http://portal.acm.org/citation.cfm?id=161724</a>。一本学术专著被论文引用不上出奇,隑־的是一本写l程序员看的技术书能被学术论文引用几百ơ,我不知道q有哪本技术书能做到这一炏V?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">TCPv1 堪称 TCP/IP领域的圣l。作?W. Richard Stevens 不是 TCP/IP 协议的发明hQ他从用者(E序员)的角度,?tcpdump 为工P?TCP 协议抽丝剥茧娓娓道来Q第17~24章)Q让人叹服。恐?TCP 协议的设计者也难以讲解得如此出Ԍ臛_不会像他q么耐心l致地画几百q收?package 的时序图?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">TCP作ؓ一个可靠的传输层协议,其核心有三点Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">1. Positive acknowledgement with retransmission</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">2. Flow control using sliding windowQ包括Nagle 法{)</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">3. Congestion controlQ包括slow start、congestion avoidance、fast retransmit{)</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">W一点已l以满?#8220;可靠?#8221;要求Qؓ什么?Q;W二ҎZ提高吞吐量,充分利用链\层带宽;W三Ҏ防止q蝲造成丢包。换a之,W二Ҏ避免发得太慢Q第三点是避免发得太快,二者相互制U。从反馈控制的角度看QTCP像是一个自适应的节阀Q根据管道的拥堵情况自动调整阀门的量?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">TCP?flow control 有一个问题,每个TCP connection是彼此独立的Q保存有自己的状态变量;一个程序如果同时开启多个连接,或者操作系l中q行多个|络E序Q这些连接似乎不知道他h的存在,~少对网卡带宽的l筹安排。(或许C的操作系l已l解决了q个问题Q)</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">TCPv1 唯一的不x它出版太早了Q?993 q至今网l技术发展了几代。链路层斚wQ当q主的 10Mbit |卡和集U器早已l被淘汰Q?00Mbit 以太|也没什么企业在用了Q交换机(switch)也已l全面取代了集线?hub)Q服务器机房?1Gbit |络ZQ有些场合甚至用上了 10Gbit 以太|。另外,无线|的普及也让TCP flow control面新挑战;原来设计TCP的时候,Z认ؓ丢包通常是拥塞造成的,q时应该放慢发送速度Q减L塞;而在无线|中Q丢包可能是信号太弱造成的,q时反而应该快速重试,以保证性能。网l层斚w变化不大QIPv6 雷声大雨点小。传输层斚wQ由于链路层带宽大增QTCP window scale option 被普遍用,另外 TCP timestamps option ?TCP selective ack option 也很常用。由于这些因素,在现在的 Linux 机器上运?tcpdump 观察 TCP 协议Q程序输Z与原书有些不同?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">一个好消息QTCPv1于今年10月(2011q_推出W二版,Amazon 的预定页面是Q?a style="color: #0066aa; text-decoration: none; ">http://www.amazon.com/gp/product/0321336313</a>Q让我们拭目以待?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· 《Unix Network Programming, Vol. 1: Networking API》第二版或第三版Q这两版的副标题E有不同Q第三版L?XTIQ,以下l称 UNPQ如果需要会?UNP2e、UNP3e l分?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">UNP是Sockets API的权威指南,但是|络~程q不是用那十几个Sockets API那么单,作?W. Richard Stevens深刻地认识到q一点,他在UNP2e的前a中写刎ͼ<a style="color: #0066aa; text-decoration: none; ">http://www.kohala.com/start/preface.unpv12e.html</a></p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">I have found when teaching network programming that about 80% of all network programming problems have nothing to do with network programming, per se. That is, the problems are not with the API functions such as accept and select, but the problems arise from a lack of understanding of the underlying network protocols. For example, I have found that once a student understands TCP's three-way handshake and four-packet connection termination, many network programming problems are immediately understood.</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">搞网l编E,一定要熟悉TCP/IP协议及其外在表现Q比如打开和关闭Nagle法Ҏ发包的媄响)Q不然出Ҏ料之外的情况摸不着头脑了。我不知道ؓ什么UNP3e在前a中去掉了q段臛_重要的话?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">另外值得一提的是,UNP中文版翻译得相当好,译者杨l张先生是真懂网l编E的?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">UNP很详l,面面俱到QUDP、TCP、IPv4、IPv6都讲C。要说有什么缺点的话,是太详l了Q重点不够突出。我十分赞同孟岩说的</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">“Q孟岩)我主张,在具备基之后Q学习Q何新东西Q都要抓住主U,H出重点。对于关键理论的学习Q要集中_֊Q速战速决。而旁枝末节和非本质性的知识内容Q完全可以留l实践去零敲打?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">“原因是这LQQ何一个高U的知识内容Q其中都只有一部分是有思想创新、有重大影响的,而其它很多东襉K是琐的、非本质的。因此,集中学习时必L握住真正重要那部分,把其它东西留l实c对于重点知识,只有集中学习其理论,才能保体系性、连贯性、正性,而对于那些旁枝末节,只有边干边学能够让你了解它们的真实h值是大是,才能让你留下更生动的印象。如果你把精力用错了地方Q比如用集中大块的时间来学习那些本来只需要查查手册就可以明白的小技巧,而对于真正重要的、思想性东西放在^旉敲碎打,那么肯定是事倍功半,甚至适得其反?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">“因此我对于市面上l大部分开发类图书都不?#8212;—它们基本上都是面向知识体pLw的Q而不是面向读者的。L把相关的所有知识细节都攑֜一堆,然后一堆一堆攒h变成一本书。反映在内容上,是毫无重点地^铺直叙,不分轻重地陈q细节,往往在第三章以前q无聊的细节谋杀了读者的热情。ؓ什么当q侯捷先生的《深入浅出MFC》和 Scott Meyers ?nbsp;<em>Effective C++</em> 能够成ؓl典Q就在于q两本书抓住了各自领域中的主qԌ提纲挈领Q纲丄张,一下子打通读者的ȝ二脉。可惜这L书太,q是已?Richard Stevens 和当?Jeffrey Richter 的书Q也只是在体pL和深入性上高h一_q不是面向读者的书?#8221;</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">什么是旁枝末节呢?拿以太网来说QCRC32如何计算是“旁枝末节”。网l程序员要明白check sum的作用,知道Z么需要check sumQ至于具体怎么CRC׃需要程序员操心。这部分通常是由|卡g完成的,在发包的时候由g填充CRCQ在收包的时候网卡自动丢弃CRC不合格的包。如果代码里边确实要用到CRC计算Q调用通用的zlibpQ也不用自己实现?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">UNP像l了你一堆做菜的原料Q各USockets 函数的用法)Q常用和不常用的都给了(Out-of-Band Data、Signal-Driven IO {等Q,要靠读者自p法取舍组合,做出一盘大菜来。在W一遍读的时候,我徏议只读那些基本且重要的章节;另外那些ơ要的内容可略作了解Q即便蟩q不M无妨。UNP是一本操作性很强的书,读这本这本书一定要上机l习?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">另外QUNP丄两个例子Q菜谱)太简单,daytime和echo一个是短连接协议,一个是长连接无格式协议Q不以覆盖基本的网l开发场景(比如 TCP包与拆包、多q接之间交换数据Q。我估计 W. Richard Stevens 原打在 UNPW三卷中讲解一些实际的例子Q只可惜他英q早逝,我等无福阅读?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">UNP是一本偏重Unix传统的书Q这本书写作的时候服务端q不需要处理成千上万的q接Q也没有现在那么多网l攻凅R书中重点介l的以accept()+fork()来处理ƈ发连接的方式在现在看来已l有点吃力,q本书的代码也没有特别防范恶意攻凅R如果工作涉及这些方面,需要再q一步学习专门的知识QC10k问题Q安全编E)?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">TCPv1和UNP应该先看哪本Q我不知道。我自己是先看的TCPv1Q花了大U半学期旉Q然后再读UNP2e和APUE?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· ?em>Effective TCP/IP Programming</em>?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">W三本书我犹豫了很久Q不知道该推荐哪本,q有哪本书能?W. Richard Stevens 的这两本比肩吗?W. Richard Stevens 为技术书c的写作树立了难以逾越的标杆,他是一位伟大的技术作家。没能看C写完 UNP W三卷实在是人生的遗憾?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">?em>Effective TCP/IP Programming</em>》这本书属于专家l验ȝc,初看时觉得收获很大,工作一D|间再看也能有新的发现。比如第6 ?#8220;TCP是一个字节流协议”Q看q这一条就不会ȝI所谓的“TCP_包问题”。我手头q本电力C?001q的中文版翻译尚可,但是很狗血的是把参考文献去掉了Q正文中引用的文章资料根本查不到名字。h?011q重新翻译出版的版本有参考文献?/p><h4>其他值得一看的?/h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">以下两本都不易读Q需要相当的基础?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· ?em>TCP/IP </em>Illustrated, <em>Vol. 2: The Implementation</em>》以下简U?TCPv2</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">1200늚大部_详细讲解?.4BSD的完整TCP/IP协议栈,注释?5,000行C源码。这本书啃下来不ҎQ如果时间不充裕Q我认ؓ没必要啃完,应用层的|络E序员选其中与工作相关的部分来阅读卛_?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q本书第一作者是Gary WrightQ从叙述风格和内容组l上是典型的“面向知识体系本n”Q先讲mbufQ再从链路层一路往上、以太网、IP|络层、ICMP、IP多播、IGMP、IP路由、多播\由、Socketspȝ调用、ARP{等。到了正文内?/4的地Ҏ开始讲TCP。面面俱到、主ơ不明?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">对于主要使用TCP的程序员Q我认ؓTCPv2一大半内容可以跌不看Q比如\p、IGMP{等Q开发网l设备的人可能更兛_q些内容Q。在工作中大可以把IP视ؓhost-to-host的协议,?#8220;IP packet如何送达Ҏ机器”的细节视为黑盒子Q这不会影响对TCP的理解和q用Q因为网l协议是分层的。这L下来Q需要看的只有三四百,四五千行代码Q大大减M负担?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q本书直接呈现高质量的工业操作pȝ源码Q读h有难度,L它甚臌?#8220;不求甚解的能?#8221;。其一Q代码只能看Q不能上行,也不能改动试验。其二,与操作系l其他部分紧密关联。比如TCP/IP stack下接|卡驱动、Y中断Q上承inode转发来的pȝ调用操作Q中间还要与q的进E文件描q符理子系l打交道Q如果要把每一部分都弄清楚Q把持不住就q失主题了。其三,一些历史包p代码变复杂晦涩。比如BSD?0q代初需要在只有4M内存的VAX上实现TCP/IPQ内存方面捉襟见肘,q才发明了mbufl构Q代码也增加了不偶发复杂度Qbuffer不连l的处理Q?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">读这套TCP/IP书切忌胶柱鼓瑟,q套书以4.4BSD为底Q其描述的行为(特别是与timer相关的行为)与现在的Linux TCP/IP有不的出入Q用书本上的知识直接套用到生产环境的Linuxpȝ可能会造成不小的误解和困扰。(TCPv3不重要,可以成套买来收藏Q不M可。)</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">· ?em>Pattern-Oriented Software Architecture Volume 2: Patterns for Concurrent and Networked Objects</em>》以下简UPOSA2</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">q本书ȝ了开发ƈ发网l服务程序的模式Q是对UNP很好的补充。UNP中的代码往往把业务逻辑和Sockets API调用混在一P代码固然短小_悍Q但是这U编码风格恐怕不适合开发大型的|络E序。POSA2模块化,|络通信交给library/frameworkdQ程序员写代码只x业务逻辑Q这是非帔R要的思想。阅读这本书对于深入理解常用的event-driven|络库(libevent、Java Netty、Java Mina、Perl POE、Python Twisted{等Q也很有帮助Q因些库都是依照q本书的思想~写的?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">POSA2的代码是C意性的Q思想很好Q细节不佟뀂其C++ 代码没有充分考虑资源的自动化理(RAII)Q如果直接按照书中介l的方式d现网l库Q那么会l用者造成不小的负担与陷阱。换a之,照他说的做,而不是照他做的学?/p><h4>不g看的?/h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">Douglas Comer 教授名气很大Q著作等w,但是他写的网l方面的书不g读,呛_D。网l编E与 TCP/IP 斚wQ有W. Richard Stevens 的书扛鼎Q计机|络原理斚wQ有Kurose?#8220;自顶向下”和Peterson?#8220;pȝ”打旗Q没其他Z么事ѝ顺便一提,Tanenbaum的操作系l教材是最好的之一Q嗯Q之二,因ؓ他写了两本:“C”?#8220;设计与实?#8221;Q,不过他的计算机网l和体系l构教材的地位比不上他的操作pȝ书的C。体pȝ构方面,Patterson ?Hennessy二h合作的两本书是最好的Q近q来崭露头角的《深入理解计机pȝ》也非常好;当然Q侧重点不同?/p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">(?</p><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; font-size: 0.75em; ">posted on 2011-06-06 08:44 <a style="color: #0066aa; text-decoration: none; ">陈硕</a> 阅读(13435) <a style="color: #0066aa; text-decoration: none; ">评论(9)</a>  <a style="color: #0066aa; text-decoration: none; ">~辑</a> <a style="color: #0066aa; text-decoration: none; ">收藏</a> <a style="color: #0066aa; text-decoration: none; ">引用</a> 所属分c? <a style="color: #0066aa; text-decoration: none; ">muduo</a></p></div><img src="http://www.cppblog.com/Solstice/aggbug/148129.html?webview=1" width="1" height="1" alt="" /><div class="wmqeeuq" id="AjaxHolder_UpdatePanel1"><a name="pagedcomment"></a><a name="评论"></a><div class="wmqeeuq" id="comments"><a name="评论"><h3>评论</h3></a><h4><a name="评论"></a><a title="permalink: re: 谈一谈网l编E学习经? style="color: #0066aa; text-decoration: none; ">#</a> <a name="148133"></a>re: 谈一谈网l编E学习经?nbsp;<span style="color: #999999; ">2011-06-06 11:55 </span><a id="AjaxHolder_Comments_CommentList_ctl00_NameLink" target="_blank">treapdb</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">果断收藏?nbsp; <a style="color: #0066aa; text-decoration: none; ">回复</a>  <a title="查看该作者发表过的评? target="_blank" style="color: #0066aa; text-decoration: none; ">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl00_DeleteLink" href="" style="color: #0066aa; text-decoration: none; "></a>  <a id="AjaxHolder_Comments_CommentList_ctl00_EditLink"></a></p><h4><a title="permalink: re: 谈一谈网l编E学习经? style="color: #0066aa; text-decoration: none; ">#</a> <a name="148144"></a>re: 谈一谈网l编E学习经?nbsp;<span style="color: #999999; ">2011-06-06 14:57 </span><a id="AjaxHolder_Comments_CommentList_ctl01_NameLink" target="_blank" style="color: #0066aa; text-decoration: none; ">千暮(zblc)</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">mark!  <a style="color: #0066aa; text-decoration: none; ">回复</a>  <a title="查看该作者发表过的评? target="_blank" style="color: #0066aa; text-decoration: none; ">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl01_DeleteLink" href="" style="color: #0066aa; text-decoration: none; "></a>  <a id="AjaxHolder_Comments_CommentList_ctl01_EditLink"></a></p><h4><a title="permalink: re: 谈一谈网l编E学习经? style="color: #0066aa; text-decoration: none; ">#</a> <a name="148152"></a>re: 谈一谈网l编E学习经?nbsp;<span style="color: #999999; ">2011-06-06 20:45 </span><a id="AjaxHolder_Comments_CommentList_ctl02_NameLink" target="_blank">nomagic</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">我也觉得ACE搞得q于复杂了,问题多多。学习一下它的某些思\和模式应该还是有些意义的Q可以开阔思\QvU百川。但是把ACE用于实际目基本是自N烦?nbsp; <a style="color: #0066aa; text-decoration: none; ">回复</a>  <a title="查看该作者发表过的评? target="_blank" style="color: #0066aa; text-decoration: none; ">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl02_DeleteLink" href="" style="color: #0066aa; text-decoration: none; "></a>  <a id="AjaxHolder_Comments_CommentList_ctl02_EditLink"></a></p><h4><a title="permalink: re: 谈一谈网l编E学习经? style="color: #0066aa; text-decoration: none; ">#</a> <a name="148162"></a>re: 谈一谈网l编E学习经?nbsp;<span style="color: #999999; ">2011-06-06 22:12 </span><a id="AjaxHolder_Comments_CommentList_ctl03_NameLink" target="_blank" style="color: #0066aa; text-decoration: none; ">陈梓?vczh)</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">@nomagic <br />那其实就是一个科学家做的demo吧,如果你仔l观察那些开发者的来源……  <a style="color: #0066aa; text-decoration: none; ">回复</a>  <a title="查看该作者发表过的评? target="_blank" style="color: #0066aa; text-decoration: none; ">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl03_DeleteLink" href="" style="color: #0066aa; text-decoration: none; "></a>  <a id="AjaxHolder_Comments_CommentList_ctl03_EditLink"></a></p><h4><a title="permalink: re: 谈一谈网l编E学习经? style="color: #0066aa; text-decoration: none; ">#</a> <a name="148163"></a>re: 谈一谈网l编E学习经?nbsp;<span style="color: #999999; ">2011-06-06 22:23 </span><a id="AjaxHolder_Comments_CommentList_ctl04_NameLink" target="_blank">jigsaw</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">服了你了。mbuf在你嘴里成了剩饭剩菜?br /><br />你除了Linux的TCP层,你还看过哪些TCP stackQ你知不知道l大多数_闭源_的TCP stack都是Zmbuf的?不管是低端手持设备还是高端的路由器,只要不是ZLinux的,一定是Zmbuf的TCP stack?br />Linux的skbuf也是处处有mbuf的媄?管Linus说他是从头写q的?br />我怀疑你qLinux的TCP stack都没看过吧?<br /><br />刚说完基的重要性,转口又嫌TCPv2太难Q还是不求甚解的?- q就是博ȝ态度?br /><br />  <a style="color: #0066aa; text-decoration: none; ">回复</a>  <a title="查看该作者发表过的评? target="_blank" style="color: #0066aa; text-decoration: none; ">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl04_DeleteLink" href="" style="color: #0066aa; text-decoration: none; "></a>  <a id="AjaxHolder_Comments_CommentList_ctl04_EditLink"></a></p><h4><a title="permalink: re: 谈一谈网l编E学习经? style="color: #0066aa; text-decoration: none; ">#</a> <a name="148185"></a>re: 谈一谈网l编E学习经?nbsp;<span style="color: #999999; ">2011-06-07 09:55 </span><a id="AjaxHolder_Comments_CommentList_ctl05_NameLink" target="_blank" style="color: #0066aa; text-decoration: none; ">zuhd</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">我主张,在具备基之后Q学习Q何新东西Q都要抓住主U,H出重点。对于关键理论的学习Q要集中_֊Q速战速决。而旁枝末节和非本质性的知识内容Q完全可以留l实践去零敲打?nbsp;<br /><br />q点我要好好学习?nbsp; <a style="color: #0066aa; text-decoration: none; ">回复</a>  <a title="查看该作者发表过的评? target="_blank" style="color: #0066aa; text-decoration: none; ">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl05_DeleteLink" href="" style="color: #0066aa; text-decoration: none; "></a>  <a id="AjaxHolder_Comments_CommentList_ctl05_EditLink"></a></p><h4><a title="permalink: re: 谈一谈网l编E学习经验[未登录]" style="color: #0066aa; text-decoration: none; ">#</a> <a name="148199"></a>re: 谈一谈网l编E学习经验[未登录] <span style="color: #999999; ">2011-06-07 14:04 </span><a id="AjaxHolder_Comments_CommentList_ctl06_NameLink" target="_blank">vincent</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">tcpv2很难看下?nbsp;<br />不知Z,也不知从何时赯来越不喜Ƣ厚重的书了  <a style="color: #0066aa; text-decoration: none; ">回复</a>  <a title="查看该作者发表过的评? target="_blank" style="color: #0066aa; text-decoration: none; ">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl06_DeleteLink" href="" style="color: #0066aa; text-decoration: none; "></a>  <a id="AjaxHolder_Comments_CommentList_ctl06_EditLink"></a></p><h4><a title="permalink: re: 谈一谈网l编E学习经?06-08更新)" style="color: #0066aa; text-decoration: none; ">#</a> <a name="148340"></a>re: 谈一谈网l编E学习经?06-08更新) <span style="color: #999999; ">2011-06-09 14:38 </span><a id="AjaxHolder_Comments_CommentList_ctl07_NameLink" target="_blank">ISO</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">jigsaw,和陈的水^在我g都是菜一, 我不但通读rfc各种文档Q还深入研究qbsd, linux tcp/ip protocol implementation, 寚w路层更是了如指掌Q对各种g的电子电器特性也很精通。你们都是菜鸟,我的服务器可以ƈ发处理上亿的tcp.  <a style="color: #0066aa; text-decoration: none; ">回复</a>  <a title="查看该作者发表过的评? target="_blank" style="color: #0066aa; text-decoration: none; ">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl07_DeleteLink" href="" style="color: #0066aa; text-decoration: none; "></a>  <a id="AjaxHolder_Comments_CommentList_ctl07_EditLink"></a></p><h4><a title="permalink: re: 谈一谈网l编E学习经?06-08更新)" style="color: #0066aa; text-decoration: none; ">#</a> <a name="148354"></a>re: 谈一谈网l编E学习经?06-08更新)<a name="Post"></a> <span style="color: #999999; ">2011-06-09 16:36 </span><a id="AjaxHolder_Comments_CommentList_ctl08_NameLink" target="_blank" style="color: #0066aa; text-decoration: none; ">陈硕</a></h4><p style="margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; ">@ISO<br />佩服佩服Q?nbsp; <a style="color: #0066aa; text-decoration: none; ">回复</a>  <a title="查看该作者发表过的评? target="_blank" style="color: #0066aa; text-decoration: none; ">更多评论</a> <a id="AjaxHolder_Comments_CommentList_ctl08_DeleteLink" href="" style="color: #0066aa; text-decoration: none; "></a>  </p></div></div></span><img src ="http://www.aygfsteel.com/xiaomage234/aggbug/352000.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/xiaomage234/" target="_blank">马?/a> 2011-06-09 17:16 <a href="http://www.aygfsteel.com/xiaomage234/archive/2011/06/09/352000.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个网卡绑定多个IP和多个网卡用一个ip的设|?/title><link>http://www.aygfsteel.com/xiaomage234/archive/2011/05/18/350462.html</link><dc:creator>马?/dc:creator><author>马?/author><pubDate>Wed, 18 May 2011 04:01:00 GMT</pubDate><guid>http://www.aygfsteel.com/xiaomage234/archive/2011/05/18/350462.html</guid><wfw:comment>http://www.aygfsteel.com/xiaomage234/comments/350462.html</wfw:comment><comments>http://www.aygfsteel.com/xiaomage234/archive/2011/05/18/350462.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/xiaomage234/comments/commentRss/350462.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/xiaomage234/services/trackbacks/350462.html</trackback:ping><description><![CDATA[常用到的?#8220;一个网卡绑定多个IP” <p>一个网卡绑定多个IP <p>linux的网l设备配|文件存攑֜/etc/sysconfig/network-scripts里面Q? <p>对于以太|的W一个网l设备,配置文g名一般ؓifcfg-eth0? <p>如果需要ؓW一个网l设备多l定一个IP地址Q只需要在 <p>/etc/sysconfig/network-scripts目录里面创徏一个名为ifcfg-eth0:0的文Ӟ <p>内容样例为: <p>DEVICE="eth0:0" <p>IPADDR="211.100.10.119" <p>NETMASK="255.255.255.0" <p>ONBOOT="yes" <p>其中的DEVICE备的名称Q? <p>IPADDR为此讑֤的IP地址Q? <p>NETMASK为子|掩? <p>ONBOOT表示在系l启动时自动启动? <p>如果需要再l定多一个IP地址Q? <p>只需要把文g名和文g内的DEVICE中的eth0:x加一卛_? <p>LINUX最多可以支?55个IP别名 <p>  <p>  <p>多个|卡l定一个IP <p>使用多块|卡虚拟成ؓ一块网卡,h相同的IP地址? <p>q项技术其实在sun和cisco中已l存在,分别UCؓTrunking和etherchannel技术, <p>在linux中,q种技术称为bonding? <p>因ؓbonding在内?.4.x中已l包含了Q? <p>只需要在~译的时候把|络讑֤选项中的Bondingdriversupport选中可以了? <p>然后Q重新编译核心,重新起动<a target="_blank"><font color="#0000ff">计算?/font></a>Q执行如下命令: <p>ismodbonding <p>ifconfigeth0down <p>ifconfigeth1down <p>ifconfigbond0ipaddress <p>ifenslavebond0eth0 <p>ifenslavebond0eth1 <p>现在两块|卡已经象一块一样工作了Q这样可以提高集节炚w的数据传输? <p>你最好把q几句写成一个脚本,再由/etc/rc.d/rc.local调用Q? <p>以便一开机就生效? <p>bonding对于服务器来是个比较好的选择Q在没有千兆|卡Ӟ <p>用两三块100兆网卡作bondingQ可大大提高服务器到交换Z间的带宽? <p>但是需要在交换Z讄q接bonding|卡的两个口子映ؓ同一个虚拟接口?/p><img src ="http://www.aygfsteel.com/xiaomage234/aggbug/350462.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/xiaomage234/" target="_blank">马?/a> 2011-05-18 12:01 <a href="http://www.aygfsteel.com/xiaomage234/archive/2011/05/18/350462.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>短连接http服务器陷?/title><link>http://www.aygfsteel.com/xiaomage234/archive/2011/05/12/350112.html</link><dc:creator>马?/dc:creator><author>马?/author><pubDate>Thu, 12 May 2011 11:26:00 GMT</pubDate><guid>http://www.aygfsteel.com/xiaomage234/archive/2011/05/12/350112.html</guid><wfw:comment>http://www.aygfsteel.com/xiaomage234/comments/350112.html</wfw:comment><comments>http://www.aygfsteel.com/xiaomage234/archive/2011/05/12/350112.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/xiaomage234/comments/commentRss/350112.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/xiaomage234/services/trackbacks/350112.html</trackback:ping><description><![CDATA[<div class="wmqeeuq" id="app-share-content"> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span>׃</span><span><font face="Times New Roman">http</font></span><span>协议的简单性以及业务的需要,我们不可避免地需要自己去实现一些走</span><span><font face="Times New Roman">http</font></span><span>协议?/span><span><font face="Times New Roman">server</font></span><span>?/span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span>当我们的短连?/span><span><font face="Times New Roman">http</font></span><span>服务?/span><span><font face="Times New Roman">(</font></span><span>如验证码服务?/span><span><font face="Times New Roman">)</font></span><span>是客L是浏览器</span><span><font face="Times New Roman">(ie</font></span><span>?/span><span><font face="Times New Roman">firefox</font></span><span>?/span><span><font face="Times New Roman">chrome)</font></span><span>的时候,有一个问题需要特别注意,我称之ؓ短连?/span><span><font face="Times New Roman">http</font></span><span>服务器陷阱。首先,先来看下面一pd同一个请求,但是不同抓包工具抓取的内容的截图Q?/span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span><font face="Times New Roman"><span style="font-size: 10.5pt; mso-bidi-font-size: 12.0pt"><img class="blogimg" src="http://hiphotos.baidu.com/yancncen/pic/item/96ea56a7a51202bed043587f.jpg" border="0" small="0" alt="" /></span></font></span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span>?/span><span><font face="Times New Roman">1.</font></span><span>使用</span><span><font face="Times New Roman">httpwatch</font></span><span>抓包获取的内?/span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span><font face="Times New Roman"><img class="blogimg" src="http://hiphotos.baidu.com/yancncen/pic/item/d68434a4883cc3dc9152ee7e.jpg" border="0" small="0" alt="" /></font></span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span>?/span><span><font face="Times New Roman">2.</font></span><span>使用</span><span><font face="Times New Roman">sniffer</font></span><span>抓包获取的内?/span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt"><span><font face="Times New Roman"></font></span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt"><span>其中Q两者是同一个请求,?/span><span><font face="Times New Roman">sniffer</font></span><span>抓包内容看、浏览器?/span><span><font face="Times New Roman">server</font></span><span>已经完成了交互过E。但是浏览器</span><span><font face="Times New Roman">(</font></span><span>包括</span><span><font face="Times New Roman">ie</font></span><span>?/span><span><font face="Times New Roman">firefox</font></span><span>?/span><span><font face="Times New Roman">chrome)</font></span><span>?/span><span><font face="Times New Roman">Result</font></span><span>却是</span><span><font face="Times New Roman">ERROR_INTERNET_CONNECTION_RESET</font></span><span>Q这是ؓ什么呢Q?/span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span>通过走读</span><span><font face="Times New Roman">server</font></span><span>代码Q发?/span><span><font face="Times New Roman">server</font></span><span>做了q样一个逻辑Q在有请求过来的时候只d?/span><span><font face="Times New Roman">100</font></span><span>个字节,因ؓ</span><span><font face="Times New Roman">server</font></span><span>认ؓq?/span><span><font face="Times New Roman">100</font></span><span>个字节够判断客L的请求行?/span><span><font face="Times New Roman">(GET /HTTP/1.0 </font></span><span>于</span><span><font face="Times New Roman">100</font></span><span>个字?/span><span><font face="Times New Roman">)</font></span><span>Q而其它请求信?/span><span><font face="Times New Roman">(</font></span><span>包括</span><span><font face="Times New Roman">cookie</font></span><span>{等</span><span><font face="Times New Roman">)</font></span><span>是无用的Q然后返?/span><span><font face="Times New Roman">response</font></span><span>信息Q然后关闭连接。流E如下:</span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span><font face="Times New Roman">1)</font></span><span>d</span><span><font face="Times New Roman">100</font></span><span>个字?/span><font face="Times New Roman"> <span>=> 2)</span></font><span>q回</span><span><font face="Times New Roman">response</font></span><span>信息</span><span><font face="Times New Roman"> => 3)</font></span><span>关闭</span><span><font face="Times New Roman">socket</font></span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span><font face="Times New Roman"></font></span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span>当客Lh的量不大的时?/span><span><font face="Times New Roman">(</font></span><span>内网开发机q发h?/span><span><font face="Times New Roman"><100)</font></span><span>、很Ҏ出现上文所q?/span><span><font face="Times New Roman">http</font></span><span>服务器陷q问题。当客户端请求的量很大的时候,出现上述问题的几率倒不大,但是偶尔也会出现。分析原因如下:</span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span>当ƈ发量很少的时候,</span><span><font face="Times New Roman">server</font></span><span>d?/span><span><font face="Times New Roman">100</font></span><span>个字节ƈq回</span><span><font face="Times New Roman">response</font></span><span>后,马上关闭q接。由于ƈ发量,</span><span><font face="Times New Roman">server</font></span><span>处理速度很快Q这样很快就会关闭了q接。但是,此时客户?/span><span><font face="Times New Roman">(</font></span><span>览?/span><span><font face="Times New Roman">)</font></span><span>也许q有一些数?/span><span><font face="Times New Roman">(</font></span><span>例如</span><span><font face="Times New Roman">cookie</font></span><span>信息{?/span><span><font face="Times New Roman">)</font></span><span>q没有真正发送到</span><span><font face="Times New Roman">server</font></span><span>的内核缓冲区。于是,览器l把剩余的数据试囑֏送到</span><span><font face="Times New Roman">server</font></span><span>Q但是,此时发现</span><span><font face="Times New Roman">server</font></span><span>已经关闭了连接,׃引发</span><span><font face="Times New Roman">ERROR_INTERNET_CONNECTION_RESET</font></span><span>错误。虽然用</span><span><font face="Times New Roman">sniffer</font></span><span>抓包发现实际上整个交互过E已l完成,但是览器缺认ؓq是一个致命的错误Q获取到的返回数据ƈ没有正确的显C在览器上?/span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span>当ƈ发量很大的时候,虽然</span><span><font face="Times New Roman">server</font></span><span>只读取了</span><span><font face="Times New Roman">100</font></span><span>个字节,但是׃服务器的处理能力有限Q从d?/span><span><font face="Times New Roman">100</font></span><span>字节到关闭连接的q程有一定的旉差。客L可以在这个时间差的时间内把剩余的数据发送到?/span><span><font face="Times New Roman">server</font></span><span>内核~冲?/span><span><font face="Times New Roman">(</font></span><span>虽然应用E序没有dq部分数?/span><span><font face="Times New Roman">)</font></span><span>。因此,出现</span><span><font face="Times New Roman">ERROR_INTERNET_CONNECTION_RESET</font></span><span>错误的概率就会变?/span></p> <p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt"><span>ȝQ在实现短连接的</span><span><font face="Times New Roman">http</font></span><span>服务?/span><span><font face="Times New Roman">(</font></span><span>其是提供给览器用的服务?/span><span><font face="Times New Roman">)</font></span><span>Ӟ量?/span><span><font face="Times New Roman">http header</font></span><span>数据包读取完_不要因ؓ只需要一部?/span><span><font face="Times New Roman">header</font></span><span>信息p处理h而不d其它的头部信息,以此来加快处理速度或者节省空间。这往往适得其反Q可能会引v一些列不可预料的问题?/span></p> <span style="font-size: 10.5pt; mso-font-kerning: 1.0pt">由此Q引发另一个思考,既然不可避免的需要读取完整的</span><span style="font-size: 10.5pt; mso-bidi-font-size: 12.0pt">http header</span><span style="font-size: 10.5pt; mso-font-kerning: 1.0pt">数据包,那么Q浏览器h的时候,应该量保持</span><span style="font-size: 10.5pt; mso-bidi-font-size: 12.0pt">http header</span><span style="font-size: 10.5pt; mso-font-kerning: 1.0pt">不要q于庞大Q既是ؓ了减~?/span><span style="font-size: 10.5pt; mso-bidi-font-size: 12.0pt">server</span><span style="font-size: 10.5pt; mso-font-kerning: 1.0pt">的压力也是ؓ了加?/span><span style="font-size: 10.5pt; mso-bidi-font-size: 12.0pt">server</span><span style="font-size: 10.5pt; mso-font-kerning: 1.0pt">的处理速度。而减?/span><span style="font-size: 10.5pt; mso-bidi-font-size: 12.0pt">http header</span><span style="font-size: 10.5pt; mso-font-kerning: 1.0pt">长度的最好方法就是减?/span><span style="font-size: 10.5pt; mso-bidi-font-size: 12.0pt">cookie</span><span style="font-size: 10.5pt; mso-font-kerning: 1.0pt">的内宏V?/span> </div> <div class="wmqeeuq" id="appShareUrl" style="clear: both"> <div class="wmqeeuq" id="appShareSafeLinkTip" style="display: none"> <div id="wmqeeuq" class="appShareErrorIcon"></div> Z您的安全Q请只打开来源可靠的网址 <p><a target="_blank">打开|站</a>    <a >取消</a></p> </div> 来自: <a target="_blank">http://hi.baidu.com/yancncen/blog/item/2b79c4a2c8e83ba7cbefd091.html</a> </div> <img src ="http://www.aygfsteel.com/xiaomage234/aggbug/350112.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/xiaomage234/" target="_blank">马?/a> 2011-05-12 19:26 <a href="http://www.aygfsteel.com/xiaomage234/archive/2011/05/12/350112.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于seo的那些事Q搜索引擎最佛_[转]http://www.aygfsteel.com/xiaomage234/archive/2010/11/11/337830.html马?/dc:creator>马?/author>Thu, 11 Nov 2010 09:07:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2010/11/11/337830.htmlhttp://www.aygfsteel.com/xiaomage234/comments/337830.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2010/11/11/337830.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/337830.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/337830.html 最q发现在效果不错。分享给大家.
    SEO中文名:搜烦引擎最佛_QSearch Engine OptimizationQ,又称为搜索引擎优化,q来较ؓ行的网l营销方式Q主要的目的是增加特定关键字的曝光率以增加网站的能见度,q而增加销售的Z?br />     SEO的主要工作是通过了解各类搜烦引擎如何抓取互联|页面、如何进行烦引以及如何确定其Ҏ一特定关键词的搜烦l果排名{技术,x遵@搜烦引擎全面而理论的机制Q对|站l构、网|字语a和站炚w的互动外交策略等q行合理规划部v来对|页q行相关的优化,使其提高搜烦引擎排名Q从而提高网站访问量Q最l提升网站的销售能力或宣传能力的技术?br />   做好seo,先要明白几个相关的术语?br />   PR|PR值全UCؓPageRank(|页U别)Q?PageRank是Google衡量|站面的重性以及Google排名的一个重要指标(PR值只对Google起作用)Q测量D围ؓ??0分别表示某网站页面的重要性。个Z人站点做到大?{于4已l很不错的了。网站查询:http://pr.chinaz.com/
   SEO收录和外?br />     通过site查询|站被收录情况,做好相关工作Q百度通过domain命oQ谷歌通过link命o。个Z用谷歌管理员工具查询更准。谷歌ؓ了避免透露   |站外部链接、恶性竞争,把很多外N屏蔽?q样做的目的也是Z保护|站的隐U?
 白帽Q保证用户体验的同时Q灵zȝq用搜烦引擎当中的一些技术规则对|站的结构、文字、权重以及外部链接做出合理部|安排,使用W合L搜烦引擎发行斚w规定的seo优化Ҏ。一般有1.l构优化?.关键词优化?.外部链接优化?.内部q接优化?br />    黑帽:注重的是短期内的利益,通过作弊手法获得很大的利?1.伪装.2.关键词堆U?3.ƺ骗性重定向.4.伪造流?4.q接工厂,特别是好多网站被黑链控制着Q大家在癑ֺ一下黑链,可以发现好多卖这斚w的。在q里我曾l看q好多政府网站都被挂q。?br />    标题titleQ这个是非常重要的,不要太长Q准规范,主题明确,明精l?最好在20个字内搞?d键词+长尾关键词_栏目名称_公司名称Q公司名U可以换成什?*|,大家有看看sina|,我觉的做的很好?br />    关键?keywordsQ搜索引擎的搜烦框中输入的Q何文字,也就是您命o搜烦引擎L的东?q个要突Z心,特别是主,可以把品关键词语写在里面,?隔开,也不要太多,10个左叻I个h感觉?br />    描述 description以简z的语句概括当前面的主要内?一定要늛主要关键词最好能出现一C?
   |页l构优化和内铑־?
   1、减目录层?br /> |站扁^化是|站l构优化的第一步。搜索引擎蜘蛛和览者都不希望他所需要的内容被隐藏的很深Q需要经q多ơ往q寻找才能到达?br /> Q大型网站,目录l构控制??以下
           a.中型|站Q目录严格控制在3以下
           b.型|站Q目录严格控制在2以下
    2 、严格控制动态网늚参数个数
在google已公布的资料中,Google明确指出动态参数小?的动态网,蜘蛛可以利抓取Q达?个参数的面Q蜘蛛将有选择的进入,而超q??个参数的动态页面,Google基本不予理睬?br /> a、防止蜘蛛被d@环套牢?br /> b、参数越多,对应的动态页多Q可能超q蜘蛛的药?br /> c、参数多Q则参数失效的几率越大?br /> d、参数多的站点存在更大的漏洞风险
    采用CSS+DIVq行|页重构
   1.表现和内容相分离
 设计部分剥d来放在一个独立样式文件中QHTML文g中只存放文本信息?br />     2.提高搜烦引擎对网늚索引效率
 用只包含l构化内容的HTML代替嵌套的标{,搜烦引擎更有效地搜索到你的|页内容Qƈ可能l你一个较高的评h?br />     3.提高面览速度
对于同一个页面视觉效果,采用CSS+DIV重构的页面容量要比TABLE~码的页面文件容量小得多Q前者一般只有后者的1/2大小?br />     4.易于l护和改?br /> 你只要简单的修改CSS文g可以重新设计整个网站的面?nbsp; 
   内容
ȝ:
       1.与网站主题相关的内容?br />        2.独特的内容,原创内容?br />        3.面内容用flashQ尽量不要用iframe或者js渲染?br />        4.囄Q还有链接alt , title加上?br />        5.面之间链接伪静态。尽量UrlRewriter?br />        6.保证|站的更C西,把爬虫喂饱?br />        7.好的|站做友情链接。不要以被Kq站的,q有q法的做链接?br />        8.最好让你的|页有别的网站{载,适当可以炒作一下?br /> 比如大家喜欢上的javaeye,大家搜烦java很多东西都会被搜索到q个|站上?br /> 做好以上几点Q提高PR|循环持进QQ重道q?br />

    SEO的将来:

   1、慢慢摸索每个网站搜索特性?br />    2.惛_好就不太Ҏ。有很多人都会碰到这L疑问Q关于排名的因素我知道已l很多了Q但自己操作h往往达不到理想的要求?br />    3.l节军_一切。SEO惛_好,靠的不是众多理论知识的熏Ӟ而是日常工作当中点点滴滴的细节的U篏?br />



]]>
L获得|通、电信、铁通IP地址分配D[转]http://www.aygfsteel.com/xiaomage234/archive/2009/11/11/301933.html马?/dc:creator>马?/author>Wed, 11 Nov 2009 02:11:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2009/11/11/301933.htmlhttp://www.aygfsteel.com/xiaomage234/comments/301933.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2009/11/11/301933.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/301933.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/301933.html
shell> wget http://ftp.apnic.net/apnic/dbase/tools/ripe-dbase-client-v3.tar.gz
shell> tar xzvf ripe-dbase-client-v3.tar.gz
shell> cd whois-3.1
shell> ./configure
shell> make

完成上述~译安装工作后,我们开始获取IP地址D;

  中国|通:shell> ./whois3 -h whois.apnic.net -l -i mb MAINT-CNCGROUP > /var/cnc

  中国电信Qshell> ./whois3 -h whois.apnic.net -l -i mb MAINT-CHINANET > /var/chinanet

  中国铁通:shell> ./whois3 -h whois.apnic.net -l -i mb MAINT-CN-CRTC > /var/crtc

  打开获取后的文g可以看到里面的信息非常详l,甚至可以看到各个分公司的负责人、电话、电子邮件等{信息。如果想得到一份整齐干净的IP地址D|Ӟ只要用grep和awk单过滤就可以了?/p>

]]>
交换机和路由器的实现原理http://www.aygfsteel.com/xiaomage234/archive/2009/03/02/257391.html马?/dc:creator>马?/author>Mon, 02 Mar 2009 10:05:00 GMThttp://www.aygfsteel.com/xiaomage234/archive/2009/03/02/257391.htmlhttp://www.aygfsteel.com/xiaomage234/comments/257391.htmlhttp://www.aygfsteel.com/xiaomage234/archive/2009/03/02/257391.html#Feedback0http://www.aygfsteel.com/xiaomage234/comments/commentRss/257391.htmlhttp://www.aygfsteel.com/xiaomage234/services/trackbacks/257391.html请问交换机和路由器分别的实现原理是什么?分别在哪个层ơ上面实现的Q?

网l互相连接v来要使用一些中间设备(或中间系l)QテQI的术语称之ؓ中Qre
layQ系l。根据中l系l所在的层次Q可以有以下五种中pȝQ?br /> 1)       物理层(卛_说的W一层、层Q?Q中l系l,卌{发器QrepeaterQ?br /> 2)       数据链\层(即第二层Q层Q?Q,即网桥或桥接器(bridgeQ?br /> 3)       |络层(W三层,层L3Q中l系l,卌\由器QrouterQ?br /> 4)       |桥和\由器的؜合物桥\器(brouterQ兼有网桥和路由器的功能?br /> 5)       在网l层以上的中l系l,即网养IgatewayQ?
当中l系l是转发器时Q一般不UC为网l互联,因ؓq仅仅是把一个网l扩大了Q而这
仍然是一个网l。高层网关由于比较复杂,目前使用得较。因此一般讨论网l互q时?br /> 是指用交换机和\由器q行互联的网l。本文主要阐qC换机和\由器及其区别?nbsp; 
2.  W二层交换机和\由器的区别:
传统交换Z|桥发展而来Q属于OQIW二层即数据链\层设备。它ҎQAQ地址?br /> 址Q通过站表选择路由Q站表的建立和维护由交换动进行。\由器属于QSQ第三层
即网l层讑֤Q它ҎQP地址q行dQ通过路由表\由协议生。因特网的\由选择
协议Q内部网兛_议IGP和外部网兛_议EGP
3. W三层交换机和\由器的区别:
在第三层交换技术出C前,几乎没有必要\由功能器件和路由器区别开来,他们完全
是相同的Q提供\由功能正在\由器的工作,然而,现在W三层交换机完全能够执行传统
路由器的大多数功能?br /> lg所qͼ交换Z般用于LQNQDQN的连接,交换机归于网桥,是数据链路层的设
备,有些交换Z可实现第三层的交换。\由器用于QPQ-QPQ之间的q接Q可以解
军_性网l之间{发分l,作用于网l层。他们只是从一条线路上接受输入分组Q然后向
另一条线路{发。这两条U\可能分属于不同的|络Qƈ采用不同协议。相比较而言Q\
由器的功能较交换强大Q但速度相对也慢Qh格昂贵,W三层交换机既有交换机线?br /> 转发报文能力Q又有\由器良好的控制功能,因此得以q播应用?/p>

----------------------------------------------------------------------

2.1    OSI和TCP/IP
1.  七层|络l构功能及特?-OSI
1)   物理层:为数据链路层提供物理q接Q在其上串行传送比ҎQ即所传送数据的单位
是比牏V此外,该层中还h定q接讑֤的电气特性和物理Ҏ等功能?br /> 2)   数据链\层:负责在网l节炚w的线路上通过、流量控制和重发{手D,无差?br /> C送以帧ؓ单位的数据。ؓ做到q一点,在每一帧中必须同时带有同步、地址、差错控
制及量控制{控制信息?br /> 3)   |络层:Z数据分l从源(源端pȝQ送到目的圎ͼ目标端系l)Q网l层的Q
务就是选择合适的路由和交换节点,使源的传输层传下来的分组信息能够正确无误地按?br /> 地址扑ֈ目的圎ͼq交付给相应的传输层Q即完成|络的寻址功能?br /> 4)   传输层:传输层是高低层之间衔接的接口层。数据传输的单位是报文,当报文较长时
它分割成若q分l?然后交给|络层进行传输。传输层是计机|络协议分层中的最关键
一层,该层以上各层不再管理信息传输问题?br /> 5)   会话层:该层对传输的报文提供同步理服务。在两个不同pȝ的互盔R信的应用进
E之间徏立、组l和协调交互。例如,定是双工还是半双工工作?br /> 6)   表示层:该层的主要Q务是把所传送的数据的抽象语法变换ؓ传送语法,x不同?br /> 机内部的不同表CŞ式{换成|络通信中的标准表示形式。此外,对传送的数据加密Q?br /> 或解密)、正文压~(或还原)也是表示层的d?br /> 7)   应用层:该层直接面向用户Q是OSI中的最高层。它的主要Q务是为用h供应用的
接口Q即提供不同计算机间的文件传送、访问与理Q电子邮件的内容处理Q不同计机
通过|络交互讉K的虚拟终端功能等?br /> 2. TCP/IP功能及特?br /> 1)   |络接口层:q是TCP/IP协议的最低一层,包括有多U逻辑链\控制和媒体访问协?br /> 。网l接口层的功能是接收IP数据报ƈ通过特定的网l进行传输,或从|络上接收物理
Q抽取出IP数据报ƈ转交l网际层?br /> 2)   |际|层QIP层)Q该层包括以下协议:IPQ网际协议)、ICMPQInternet Contro
l Message Protocol,因特|控制报文协议)、ARPQAddress Resolution ProtocolQ地址
解析协议Q、RARPQReverse Address Resolution ProtocolQ反向地址解析协议Q。该?br /> 负责相同或不同网l中计算Z间的通信,主要处理数据报和路由。在IP层中QARP协议?br /> 于将IP地址转换成物理地址,RARP协议用于物理地址转换成IP地址QICMP协议用于报告?br /> 错和传送控制信息。IP协议在TCP/IP协议l中处于核心C?br /> 3)   传输层:该层提供TCPQ传输控制协议)和UDPQUser Datagram ProtocolQ用h?br /> 报协议)两个协议Q它们都建立在IP协议的基上,其中TCP提供可靠的面向连接服务,U
DP提供单的无连接服务。传输层提供端到端,卛_用程序之间的通信Q主要功能是数据
格式化、数据确认和丢失重传{?br /> 4)   应用层:TCP/IP协议的应用层相当于OSI模型的会话层、表C层和应用层Q它向用?br /> 提供一l常用的应用层协?其中包括QTelnet、SMTP、DNS{。此外,在应用层中还包含
有用户应用程序,它们均是建立在TCP/IP协议l之上的专用E序?br /> 3. OSI参考模型和TCP/IP参考模型的区别Q?br /> 1)   OSI模型?层,TCP/IP只有4层;
2)   OSI先于协议出现Q因此不会偏向于M一l特定的协议Q通用性更强,但有些功?br /> 不知该放哪一层上Q因此不得不加入一些子层;TCP/IP后于协议出现Q仅是将已有协议?br /> 一个描qͼ因此两者配合的非常好;但他不适合其他的协议栈Q不Ҏ描述其他非TCP/IP
的网l;
3)   OSI中网l层同时支持无连接和面向q接的通信Q但在传输层上只支持面向q接的?br /> 信;TCP/IP中网l层只支持无q接通信Q传输层同时支持两种通信Q?br /> 4)   在技术发生变化时QOSI模型比TCP/IP模型中的协议更容易被替换?br /> 4.         请你详细的解释一下IP协议的定义,在哪个层上面Q主要有什么作用? TCP?br /> UDP呢? 
解:与IP协议配套使用的还有三个协?
ARP-地址解析协议
RARPQ逆地址解析协议
ICMPQ因特网控制报文协议ICMP
IP协议Q网际协?br /> IP地址、IP包头



]]>
վ֩ģ壺 | | żҸ| ɽ| ͬ| Դ| ˮ| | | ˮ| | | | | | | | | | | ͬ| ľ| | | | | Դ| | ̩| | | | | | ̨| | ľ| ɽ| | ˮ| |