Windows网络与通信程序设计的目录

Windows网络与通信程序设计的目录,第1张

第1章 计算机网络基础

11网络的概念和网络的组成

12计算机网络参考模型

121协议层次

122TCP/IP参考模型

123应用层(Application Layer)

124传输层(Transport Layer)

125网络层(Network Layer)

126链路层(Link Layer)

127物理层(Physical Layer)

13网络程序寻址方式

131 MAC地址

132 IP地址

133子网寻址

134端口号

135网络地址转换(NAT)

14网络应用程序设计基础

141网络程序体系结构

142网络程序通信实体

143网络程序开发环境

第2章 Winsock编程接口

21 Winsock库

211 Winsock库的装入和释放

212封装CInitSock类

22 Winsock的寻址方式和字节顺序

221 Winsock寻址

222字节顺序

223获取地址信息

23 Winsock编程详解

231 Winsock编程流程

232典型过程图

233 TCP服务器和客户端程序举例

234 UDP编程

24网络对时程序实例

241时间协议(Time Protocol)

242 TCP/IP实现代码

第3章 Windows套接字I/O模型

31套接字模式

311阻塞模式

312非阻塞模式

32选择(select)模型

321 select函数

322应用举例

33 WSAAsyncSelect模型

331消息通知和WSAAsyncSelect函数

332应用举例

34 WSAEventSelect模型

341 WSAEventSelect函数

342应用举例

343基于WSAEventSelect模型的服务器设计

35重叠(Overlapped)I/O模型

351重叠I/O函数

352事件通知方式

353基于重叠I/O模型的服务器设计

第4章 IOCP与可伸缩网络程序

41完成端口I/O模型

411什么是完成端口(completion port)对象

412使用IOCP的方法

413示例程序

414恰当地关闭IOCP

42 Microsoft扩展函数

421 GetAcceptExSockaddrs函数

422 TransmitFile函数

423 TransmitPackets函数

424 ConnectEx函数

425 DisconnectEx函数

43可伸缩服务器设计注意事项

431内存资源管理

432接受连接的方法

433恶意客户连接问题

434包重新排序问题

44可伸缩服务器系统设计实例

441 CIOCPServer类的总体结构

442数据结构定义和内存池方案

443自定义帮助函数

444开启服务和停止服务

445 I/O处理线程

446用户接口和测试程序

第5章 互联网广播和IP多播

51套接字选项和I/O控制命令

511套接字选项

512 I/O控制命令

52广播通信

53 IP多播(Multicasting)

531多播地址

532组管理协议(IGMP)

533使用IP多播

54基于IP多播的组讨论会实例

541定义组讨论会协议

542线程通信机制

543封装CGroupTalk类

544程序界面

第6章 原始套接字

第7章 Winsock服务提供者接口(SPI)

第8章 Windows网络驱动接口标准(NDIS)和协议驱动的开发

第9章 网络扫描与检测技术

第10章 点对点(P2P)网络通信技术

第11章 核心层网络封包截获技术

第12章 Windows网络防火墙开发技术

第13章 IP帮助函数

第14章 Email协议及其编程

……

作者:美团技术团队

链接:https://zhuanlanzhihucom/p/23488863

来源:知乎

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

NIO(Non-blocking I/O,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接、I/O处理问题的有效方式。

那么NIO的本质是什么样的呢?它是怎样与事件模型结合来解放线程、提高系统吞吐的呢?

本文会从传统的阻塞I/O和线程池模型面临的问题讲起,然后对比几种常见I/O模型,一步步分析NIO怎么利用事件模型处理I/O,解决线程池瓶颈处理海量连接,包括利用面向事件的方式编写服务端/客户端程序。最后延展到一些高级主题,如Reactor与Proactor模型的对比、Selector的唤醒、Buffer的选择等。

注:本文的代码都是伪代码,主要是为了示意,不可用于生产环境。

传统BIO模型分析

让我们先回忆一下传统的服务器端同步阻塞I/O处理(也就是BIO,Blocking I/O)的经典编程模型:

{

ExecutorService executor = ExcutorsnewFixedThreadPollExecutor(100);//线程池

ServerSocket serverSocket = new ServerSocket();

serverSocketbind(8088);

while(!ThreadcurrentThreadisInturrupted()){//主线程死循环等待新连接到来

Socket socket = serverSocketaccept();

executorsubmit(new ConnectIOnHandler(socket));//为新的连接创建新的线程

}

class ConnectIOnHandler extends Thread{

private Socket socket;

public ConnectIOnHandler(Socket socket){

thissocket = socket;

}

public void run(){

while(!ThreadcurrentThreadisInturrupted()&&!socketisClosed()){死循环处理读写事件

String someThing = socketread()//读取数据

if(someThing!=null){

//处理数据

socketwrite()//写数据

}

}

}

}

这是一个经典的每连接每线程的模型,之所以使用多线程,主要原因在于socketaccept()、socketread()、socketwrite()三个主要函数都是同步阻塞的,当一个连接在处理I/O的时候,系统是阻塞的,如果是单线程的话必然就挂死在那里;但CPU是被释放出来的,开启多线程,就可以让CPU去处理更多的事情。其实这也是所有使用多线程的本质:

利用多核。

当I/O阻塞系统,但CPU空闲的时候,可以利用多线程使用CPU资源。

现在的多线程一般都使用线程池,可以让线程的创建和回收成本相对较低。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的I/O并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。

不过,这个模型最本质的问题在于,严重依赖于线程。但线程是很"贵"的资源,主要表现在:

线程的创建和销毁成本很高,在Linux这样的操作系统中,线程本质上就是一个进程。创建和销毁都是重量级的系统函数。

线程本身占用较大内存,像Java的线程栈,一般至少分配512K~1M的空间,如果系统中的线程数过千,恐怕整个JVM的内存都会被吃掉一半。

线程的切换成本是很高的。操作系统发生线程切换的时候,需要保留线程的上下文,然后执行系统调用。如果线程数过高,可能执行线程切换的时间甚至会大于线程执行的时间,这时候带来的表现往往是系统load偏高、CPU sy使用率特别高(超过20%以上),导致系统几乎陷入不可用的状态。

容易造成锯齿状的系统负载。因为系统负载是用活动线程数或CPU核心数,一旦线程数量高但外部网络环境不是很稳定,就很容易造成大量请求的结果同时返回,激活大量阻塞线程从而使系统负载压力过大。

所以,当面对十万甚至百万级连接的时候,传统的BIO模型是无能为力的。随着移动端应用的兴起和各种网络游戏的盛行,百万级长连接日趋普遍,此时,必然需要一种更高效的I/O处理模型。

NIO是怎么工作的

很多刚接触NIO的人,第一眼看到的就是Java相对晦涩的API,比如:Channel,Selector,Socket什么的;然后就是一坨上百行的代码来演示NIO的服务端Demo……瞬间头大有没有?

我们不管这些,抛开现象看本质,先分析下NIO是怎么工作的。

常见I/O模型对比

所有的系统I/O都分为两个阶段:等待就绪和操作。举例来说,读函数,分为等待系统可读和真正的读;同理,写函数分为等待网卡可以写和真正的写。

需要说明的是等待就绪的阻塞是不使用CPU的,是在“空等”;而真正的读写操作的阻塞是使用CPU的,真正在"干活",而且这个过程非常快,属于memory copy,带宽通常在1GB/s级别以上,可以理解为基本不耗时。

下图是几种常见I/O模型的对比:

以socketread()为例子:

传统的BIO里面socketread(),如果TCP RecvBuffer里没有数据,函数会一直阻塞,直到收到数据,返回读到的数据。

对于NIO,如果TCP RecvBuffer有数据,就把数据从网卡读到内存,并且返回给用户;反之则直接返回0,永远不会阻塞。

最新的AIO(Async I/O)里面会更进一步:不但等待就绪是非阻塞的,就连数据从网卡到内存的过程也是异步的。

换句话说,BIO里用户最关心“我要读”,NIO里用户最关心"我可以读了",在AIO模型里用户更需要关注的是“读完了”。

NIO一个重要的特点是:socket主要的读、写、注册和接收函数,在等待就绪阶段都是非阻塞的,真正的I/O操作是同步阻塞的(消耗CPU但性能非常高)。

如何结合事件模型使用NIO同步非阻塞特性

回忆BIO模型,之所以需要多线程,是因为在进行I/O操作的时候,一是没有办法知道到底能不能写、能不能读,只能"傻等",即使通过各种估算,算出来操作系统没有能力进行读写,也没法在socketread()和socketwrite()函数中返回,这两个函数无法进行有效的中断。所以除了多开线程另起炉灶,没有好的办法利用CPU。

NIO的读写函数可以立刻返回,这就给了我们不开线程利用CPU的最好机会:如果一个连接不能读写(socketread()返回0或者socketwrite()返回0),我们可以把这件事记下来,记录的方式通常是在Selector上注册标记位,然后切换到其它就绪的连接(channel)继续进行读写。

下面具体看下如何利用事件模型单线程处理所有I/O请求:

NIO的主要事件有几个:读就绪、写就绪、有新连接到来。

我们首先需要注册当这几个事件到来的时候所对应的处理器。然后在合适的时机告诉事件选择器:我对这个事件感兴趣。对于写操作,就是写不出去的时候对写事件感兴趣;对于读操作,就是完成连接和系统没有办法承载新读入的数据的时;对于accept,一般是服务器刚启动的时候;而对于connect,一般是connect失败需要重连或者直接异步调用connect的时候。

其次,用一个死循环选择就绪的事件,会执行系统调用(Linux 26之前是select、poll,26之后是epoll,Windows是IOCP),还会阻塞的等待新事件的到来。新事件到来的时候,会在selector上注册标记位,标示可读、可写或者有连接到来。

注意,select是阻塞的,无论是通过操作系统的通知(epoll)还是不停的轮询(select,poll),这个函数是阻塞的。所以你可以放心大胆地在一个while(true)里面调用这个函数而不用担心CPU空转。

所以我们的程序大概的模样是:

  interface ChannelHandler{

     void channelReadable(Channel channel);

     void channelWritable(Channel channel);

  }

  class Channel{

    Socket socket;

    Event event;//读,写或者连接

  }

  //IO线程主循环:

  class IoThread extends Thread{

  public void run(){

  Channel channel;

  while(channel=Selectorselect()){//选择就绪的事件和对应的连接

     if(channelevent==accept){

        registerNewChannelHandler(channel);//如果是新连接,则注册一个新的读写处理器

     }

     if(channelevent==write){

        getChannelHandler(channel)channelWritable(channel);//如果可以写,则执行写事件

     }

     if(channelevent==read){

         getChannelHandler(channel)channelReadable(channel);//如果可以读,则执行读事件

     }

   }

  }

  Map<Channel,ChannelHandler> handlerMap;//所有channel的对应事件处理器

 }

这个程序很简短,也是最简单的Reactor模式:注册所有感兴趣的事件处理器,单线程轮询选择就绪事件,执行事件处理器。

优化线程模型

由上面的示例我们大概可以总结出NIO是怎么解决掉线程的瓶颈并处理海量连接的:

NIO由原来的阻塞读写(占用线程)变成了单线程轮询事件,找到可以进行读写的网络描述符进行读写。除了事件的轮询是阻塞的(没有可干的事情必须要阻塞),剩余的I/O操作都是纯CPU操作,没有必要开启多线程。

并且由于线程的节约,连接数大的时候因为线程切换带来的问题也随之解决,进而为处理海量连接提供了可能。

单线程处理I/O的效率确实非常高,没有线程切换,只是拼命的读、写、选择事件。但现在的服务器,一般都是多核处理器,如果能够利用多核心进行I/O,无疑对效率会有更大的提高。

仔细分析一下我们需要的线程,其实主要包括以下几种:

事件分发器,单线程选择就绪的事件。

I/O处理器,包括connect、read、write等,这种纯CPU操作,一般开启CPU核心个线程就可以。

业务线程,在处理完I/O后,业务一般还会有自己的业务逻辑,有的还会有其他的阻塞I/O,如DB操作,RPC等。只要有阻塞,就需要单独的线程。

Java的Selector对于Linux系统来说,有一个致命限制:同一个channel的select不能被并发的调用。因此,如果有多个I/O线程,必须保证:一个socket只能属于一个IoThread,而一个IoThread可以管理多个socket。

另外连接的处理和读写的处理通常可以选择分开,这样对于海量连接的注册和读写就可以分发。虽然read()和write()是比较高效无阻塞的函数,但毕竟会占用CPU,如果面对更高的并发则无能为力。

NIO在客户端的魔力

通过上面的分析,可以看出NIO在服务端对于解放线程,优化I/O和处理海量连接方面,确实有自己的用武之地。那么在客户端上,NIO又有什么使用场景呢

常见的客户端BIO+连接池模型,可以建立n个连接,然后当某一个连接被I/O占用的时候,可以使用其他连接来提高性能。

但多线程的模型面临和服务端相同的问题:如果指望增加连接数来提高性能,则连接数又受制于线程数、线程很贵、无法建立很多线程,则性能遇到瓶颈。

每连接顺序请求的Redis

对于Redis来说,由于服务端是全局串行的,能够保证同一连接的所有请求与返回顺序一致。这样可以使用单线程+队列,把请求数据缓冲。然后pipeline发送,返回future,然后channel可读时,直接在队列中把future取回来,done()就可以了。

伪代码如下:

class RedisClient Implements ChannelHandler{

private BlockingQueue CmdQueue;

private EventLoop eventLoop;

private Channel channel;

class Cmd{

 String cmd;

 Future result;

}

public Future get(String key){

  Cmd cmd= new Cmd(key);

  queueoffer(cmd);

  eventLoopsubmit(new Runnable(){

       List list = new ArrayList();

       queuedrainTo(list);

       if(channelisWritable()){

        channelwriteAndFlush(list);

       }

  });

}

public void ChannelReadFinish(Channel channel,Buffer Buffer){

   List result = handleBuffer();//处理数据

   //从cmdQueue取出future,并设值,futuredone();

}

public void ChannelWritable(Channel channel){

  channelflush();

}

}

这样做,能够充分的利用pipeline来提高I/O能力,同时获取异步处理能力。

多连接短连接的HttpClient

类似于竞对抓取的项目,往往需要建立无数的HTTP短连接,然后抓取,然后销毁,当需要单机抓取上千网站线程数又受制的时候,怎么保证性能呢

何不尝试NIO,单线程进行连接、写、读操作?如果连接、读、写操作系统没有能力处理,简单的注册一个事件,等待下次循环就好了。

如何存储不同的请求/响应呢?由于http是无状态没有版本的协议,又没有办法使用队列,好像办法不多。比较笨的办法是对于不同的socket,直接存储socket的引用作为map的key。

常见的RPC框架,如Thrift,Dubbo

这种框架内部一般维护了请求的协议和请求号,可以维护一个以请求号为key,结果的result为future的map,结合NIO+长连接,获取非常不错的性能。

NIO高级主题

Proactor与Reactor

一般情况下,I/O 复用机制需要事件分发器(event dispatcher)。 事件分发器的作用,即将那些读写事件源分发给各读写事件的处理者,就像送快递的在楼下喊: 谁谁谁的快递到了, 快来拿吧!开发人员在开始的时候需要在分发器那里注册感兴趣的事件,并提供相应的处理者(event handler),或者是回调函数;事件分发器在适当的时候,会将请求的事件分发给这些handler或者回调函数。

涉及到事件分发器的两种模式称为:Reactor和Proactor。 Reactor模式是基于同步I/O的,而Proactor模式是和异步I/O相关的。在Reactor模式中,事件分发器等待某个事件或者可应用或个操作的状态发生(比如文件描述符可读写,或者是socket可读写),事件分发器就把这个事件传给事先注册的事件处理函数或者回调函数,由后者来做实际的读写操作。

而在Proactor模式中,事件处理者(或者代由事件分发器发起)直接发起一个异步读写操作(相当于请求),而实际的工作是由操作系统来完成的。发起时,需要提供的参数包括用于存放读到数据的缓存区、读的数据大小或用于存放外发数据的缓存区,以及这个请求完后的回调函数等信息。事件分发器得知了这个请求,它默默等待这个请求的完成,然后转发完成事件给相应的事件处理者或者回调。举例来说,在Windows上事件处理者投递了一个异步IO操作(称为overlapped技术),事件分发器等IO Complete事件完成。这种异步模式的典型实现是基于操作系统底层异步API的,所以我们可称之为“系统级别”的或者“真正意义上”的异步,因为具体的读写是由操作系统代劳的。

举个例子,将有助于理解Reactor与Proactor二者的差异,以读操作为例(写操作类似)。

在Reactor中实现读

注册读就绪事件和相应的事件处理器。

事件分发器等待事件。

事件到来,激活分发器,分发器调用事件对应的处理器。

事件处理器完成实际的读操作,处理读到的数据,注册新的事件,然后返还控制权。

在Proactor中实现读:

处理器发起异步读操作(注意:操作系统必须支持异步IO)。在这种情况下,处理器无视IO就绪事件,它关注的是完成事件。

事件分发器等待操作完成事件。

在分发器等待过程中,操作系统利用并行的内核线程执行实际的读操作,并将结果数据存入用户自定义缓冲区,最后通知事件分发器读操作完成。

事件分发器呼唤处理器。

事件处理器处理用户自定义缓冲区中的数据,然后启动一个新的异步操作,并将控制权返回事件分发器。

可以看出,两个模式的相同点,都是对某个I/O事件的事件通知(即告诉某个模块,这个I/O操作可以进行或已经完成)。在结构上,两者也有相同点:事件分发器负责提交IO操作(异步)、查询设备是否可操作(同步),然后当条件满足时,就回调handler;不同点在于,异步情况下(Proactor),当回调handler时,表示I/O操作已经完成;同步情况下(Reactor),回调handler时,表示I/O设备可以进行某个操作(can read 或 can write)。

下面,我们将尝试应对为Proactor和Reactor模式建立可移植框架的挑战。在改进方案中,我们将Reactor原来位于事件处理器内的Read/Write操作移至分发器(不妨将这个思路称为“模拟异步”),以此寻求将Reactor多路同步I/O转化为模拟异步I/O。以读操作为例子,改进过程如下:

注册读就绪事件和相应的事件处理器。并为分发器提供数据缓冲区地址,需要读取数据量等信息。

分发器等待事件(如在select()上等待)。

事件到来,激活分发器。分发器执行一个非阻塞读操作(它有完成这个操作所需的全部信息),最后调用对应处理器。

事件处理器处理用户自定义缓冲区的数据,注册新的事件(当然同样要给出数据缓冲区地址,需要读取的数据量等信息),最后将控制权返还分发器。

如我们所见,通过对多路I/O模式功能结构的改造,可将Reactor转化为Proactor模式。改造前后,模型实际完成的工作量没有增加,只不过参与者间对工作职责稍加调换。没有工作量的改变,自然不会造成性能的削弱。对如下各步骤的比较,可以证明工作量的恒定:

标准/典型的Reactor:

步骤1:等待事件到来(Reactor负责)。

步骤2:将读就绪事件分发给用户定义的处理器(Reactor负责)。

步骤3:读数据(用户处理器负责)。

步骤4:处理数据(用户处理器负责)。

改进实现的模拟Proactor:

步骤1:等待事件到来(Proactor负责)。

步骤2:得到读就绪事件,执行读数据(现在由Proactor负责)。

步骤3:将读完成事件分发给用户处理器(Proactor负责)。

步骤4:处理数据(用户处理器负责)。

对于不提供异步I/O API的操作系统来说,这种办法可以隐藏Socket API的交互细节,从而对外暴露一个完整的异步接口。借此,我们就可以进一步构建完全可移植的,平台无关的,有通用对外接口的解决方案。

代码示例如下:

interface ChannelHandler{

     void channelReadComplate(Channel channel,byte[] data);

     void channelWritable(Channel channel);

  }

  class Channel{

    Socket socket;

    Event event;//读,写或者连接

  }

  //IO线程主循环:

  class IoThread extends Thread{

  public void run(){

  Channel channel;

  while(channel=Selectorselect()){//选择就绪的事件和对应的连接

     if(channelevent==accept){

        registerNewChannelHandler(channel);//如果是新连接,则注册一个新的读写处理器

        Selectorinterested(read);

     }

     if(channelevent==write){

        getChannelHandler(channel)channelWritable(channel);//如果可以写,则执行写事件

     }

     if(channelevent==read){

         byte[] data = channelread();

         if(channelread()==0)//没有读到数据,表示本次数据读完了

         {

         getChannelHandler(channel)channelReadComplate(channel,data;//处理读完成事件

         }

         if(过载保护){

         Selectorinterested(read);

         }

     }

    }

   }

  Map<Channel,ChannelHandler> handlerMap;//所有channel的对应事件处理器

  }

Selectorwakeup()

主要作用

解除阻塞在Selectorselect()/select(long)上的线程,立即返回。

两次成功的select之间多次调用wakeup等价于一次调用。

如果当前没有阻塞在select上,则本次wakeup调用将作用于下一次select——“记忆”作用。

为什么要唤醒?

注册了新的channel或者事件。

channel关闭,取消注册。

优先级更高的事件触发(如定时器事件),希望及时处理。

原理

Linux上利用pipe调用创建一个管道,Windows上则是一个loopback的tcp连接。这是因为win32的管道无法加入select的fd set,将管道或者TCP连接加入select fd set。

wakeup往管道或者连接写入一个字节,阻塞的select因为有I/O事件就绪,立即返回。可见,wakeup的调用开销不可忽视。

Buffer的选择

通常情况下,操作系统的一次写操作分为两步:

将数据从用户空间拷贝到系统空间。

从系统空间往网卡写。同理,读操作也分为两步:

① 将数据从网卡拷贝到系统空间;

② 将数据从系统空间拷贝到用户空间。

对于NIO来说,缓存的使用可以使用DirectByteBuffer和HeapByteBuffer。如果使用了DirectByteBuffer,一般来说可以减少一次系统空间到用户空间的拷贝。但Buffer创建和销毁的成本更高,更不宜维护,通常会用内存池来提高性能。

如果数据量比较小的中小应用情况下,可以考虑使用heapBuffer;反之可以用directBuffer。

NIO存在的问题

使用NIO != 高性能,当连接数<1000,并发程度不高或者局域网环境下NIO并没有显著的性能优势。

NIO并没有完全屏蔽平台差异,它仍然是基于各个操作系统的I/O系统实现的,差异仍然存在。使用NIO做网络编程构建事件驱动模型并不容易,陷阱重重。

推荐大家使用成熟的NIO框架,如Netty,MINA等。解决了很多NIO的陷阱,并屏蔽了操作系统的差异,有较好的性能和编程模型。

老司机带你分析SpringMVC框架设计原理与实现

链接:https://panbaiducom/s/1cksL0_VmSMdkIXWFSOx19g

密码:57w4

Netty粘包分包现象及解决方案实战,防socket攻击

链接:https://panbaiducom/s/1kTF2oqHOqvrPJrKa7TpXOQ

密码:dk9n

大型企业级高并发下数据库水平切分之读写分离技巧详解

链接:https://panbaiducom/s/1OrXSGCCboqgVX2vgfC7Z7Q

密码:ri8q

分布式事务出现场景及解决方案详细剖析

链接:https://panbaiducom/s/1BBf6cePibN0xawFEY7A6ZA

密码:380p

以上都是小编收集了大神的灵药,喜欢的拿走吧!喜欢小编就轻轻关注一下吧!

Windows网络与通信程序设计(第2版) 王艳平 这本书写的非常好,我有本王艳平写的 windows程序设计,写得很好,我自己不做网络开发,就没有买网络的那本书!不过推荐你看看,真的很不错!

本书将编程方法、网络协议和应用实例有机结合起来,详细阐明Windows网络编程的各方面内容。本书首先介绍Windows平台上进行网络编程的基础知识,包括网络硬件、术语、协议、Winsock编程接口和各种I/O方法等;然后通过具体实例详细讲述当前流行的高性能可伸缩服务器设计、IP多播和Internet广播、P2P程序设计、原始套接字、SPI、协议驱动的开发和原始以太数据的发送、ARP欺骗技术、LAN和WAN上的扫描和侦测技术、个人防火墙与网络封包截获技术等;最后讲述IP帮助函数和E-mail的开发方法。 本书结构紧凑,内容由浅入

第1章 计算机网络基础 1

11 网络的概念和网络的组成 1

12 计算机网络参考模型 2

121 协议层次 2

122 TCP/IP参考模型 2

123 应用层(Application Layer) 3

124 传输层(Transport Layer) 3

125 网络层(Network Layer) 3

126 链路层(Link Layer) 4

127 物理层(Physical Layer) 4

13 网络程序寻址方式 4

131 MAC地址 4

132 IP地址 5

133 子网寻址 6

134 端口号 8

135 网络地址转换(NAT) 8

14 网络应用程序设计基础 10

141 网络程序体系结构 10

142 网络程序通信实体 11

143 网络程序开发环境 12

第2章 Winsock编程接口 13

21 Winsock库 13

211 Winsock库的装入和释放 13

212 封装CInitSock类 14

22 Winsock的寻址方式和字节顺序 14

221 Winsock寻址 14

222 字节顺序 16

223 获取地址信息 17

23 Winsock编程详解 20

231 Winsock编程流程 20

232 典型过程图 23

233 TCP服务器和客户端程序举例 24

234 UDP编程 26

24 网络对时程序实例 28

241 时间协议(Time Protocol) 28

242 TCP/IP实现代码 29

第3章 Windows套接字I/O模型 31

31 套接字模式 31

311 阻塞模式 31

312 非阻塞模式 31

32 选择(select)模型 32

321 select函数 32

322 应用举例 33

33 WSAAsyncSelect模型 36

331 消息通知和WSAAsyncSelect函数 36

332 应用举例 37

34 WSAEventSelect模型 40

341 WSAEventSelect函数 40

342 应用举例 42

343 基于WSAEventSelect模型的服务器设计 44

35 重叠(Overlapped)I/O模型 53

351 重叠I/O函数 53

352 事件通知方式 56

353 基于重叠I/O模型的服务器设计 56

第4章 IOCP与可伸缩网络程序 67

41 完成端口I/O模型 67

411 什么是完成端口(completion port)对象 67

412 使用IOCP的方法 67

413 示例程序 69

414 恰当地关闭IOCP 72

42 Microsoft扩展函数 72

421 GetAcceptExSockaddrs函数 73

422 TransmitFile函数 73

423 TransmitPackets函数 74

424 ConnectEx函数 75

425 DisconnectEx函数 76

43 可伸缩服务器设计注意事项 76

431 内存资源管理 76

432 接受连接的方法 77

433 恶意客户连接问题 77

434 包重新排序问题 78

44 可伸缩服务器系统设计实例 78

441 CIOCPServer类的总体结构 78

442 数据结构定义和内存池方案 82

443 自定义帮助函数 85

444 开启服务和停止服务 88

445 I/O处理线程 93

446 用户接口和测试程序 99

第5章 互联网广播和IP多播 100

51 套接字选项和I/O控制命令 100

511 套接字选项 100

512 I/O控制命令 102

52 广播通信 103

53 IP多播(Multicasting) 105

531 多播地址 105

532 组管理协议(IGMP) 105

533 使用IP多播 106

54 基于IP多播的组讨论会实例 110

541 定义组讨论会协议 110

542 线程通信机制 111

543 封装CGroupTalk类 111

544 程序界面 117

第6章 原始套接字 121

61 使用原始套接字 121

62 ICMP编程 121

621 ICMP与校验和的计算 121

622 Ping程序实例 124

623 路由跟踪 126

63 使用IP头包含选项 129

631 IP数据报格式 129

632 UDP数据报格式 131

633 原始UDP封包发送实例 133

64 网络嗅探器开发实例 134

641 嗅探器设计原理 135

642 网络嗅探器的具体实现 136

643 侦听局域网内的密码 138

65 TCP通信开发实例 140

651 创建一个原始套接字,并设置IP头选项 140

652 构造IP头和TCP头 140

653 发送原始套接字数据报 142

654 接收数据 146

第7章 Winsock服务提供者接口(SPI) 147

71 SPI概述 147

72 Winsock协议目录 148

721 协议特性 149

722 使用Winsock API函数枚举协议 150

723 使用Winsock SPI函数枚举协议 151

73 分层服务提供者(LSP) 153

731 运行原理 153

732 安装LSP 154

733 移除LSP 158

734 编写LSP 159

735 LSP实例 161

74 基于SPI的数据报过滤实例 165

75 基于Winsock的网络聊天室开发 171

751 服务端 171

752 客户端 171

753 聊天室程序的设计说明 172

754 核心代码分析 172

第8章 Windows网络驱动接口标准(NDIS)和协议驱动的开发 176

81 核心层网络驱动 176

811 Windows 2000及其后产品的网络体系结构 176

812 NDIS网络驱动程序 177

813 网络驱动开发环境 178

82 WDM驱动开发基础 181

821 UNICODE字符串 181

822 设备对象 181

823 驱动程序的基本结构 183

824 I/O请求包(I/O request packet,IRP)和I/O堆栈 183

825 完整驱动程序示例 186

826 扩展派遣接口 188

827 应用举例(进程诊测实例) 191

83 开发NDIS网络驱动预备知识 198

831 中断请求级别(Interrupt Request Level,IRQL) 198

832 旋转锁(Spin Lock) 198

833 双链表 199

834 封包结构 199

84 NDIS协议驱动 200

841 注册协议驱动 200

842 打开下层协议驱动的适配器 201

843 协议驱动的封包管理 202

844 在协议驱动中接收数据 203

845 从协议驱动发送封包 204

85 NDIS协议驱动开发实例 204

851 总体设计 204

852 NDIS协议驱动的初始化、注册和卸载 206

853 下层NIC的绑定和解除绑定 209

854 发送数据 217

855 接收数据 219

856 用户IOCTL处理 225

第9章 网络扫描与检测技术 233

91 网络扫描基础知识 233

911 以太网数据帧 233

912 ARP 234

913 ARP格式 236

914 SendARP函数 237

92 原始以太封包的发送 238

921 安装协议驱动 238

922 协议驱动用户接口 238

923 发送以太封包的测试程序 244

93 局域网计算机扫描 245

931 管理原始ARP封包 246

932 ARP扫描示例 249

94 互联网计算机扫描 253

941 端口扫描原理 253

942 半开端口扫描实现 254

95 ARP欺骗原理与实现 259

951 IP欺骗的用途和实现原理 259

952 IP地址冲突 260

953 ARP欺骗示例 261

第10章 点对点(P2P)网络通信技术 264

101 P2P穿越概述 264

102 一般概念 265

1021 NAT术语 265

1022 中转 265

1023 反向连接 266

103 UDP打洞 267

1031 中心服务器 267

1032 建立点对点会话 267

1033 公共NAT后面的节点 267

1034 不同NAT后面的节点 268

1035 多级NAT后面的节点 269

1036 UDP空闲超时 270

104 TCP打洞 271

1041 套接字和TCP端口重用 271

1042 打开点对点的TCP流 271

1043 应用程序看到的行为 272

1044 同步TCP打开 273

105 Internet点对点通信实例 273

1051 总体设计 273

1052 定义P2P通信协议 274

1053 客户方程序 275

1054 服务器方程序 287

1055 测试程序 291

第11章 核心层网络封包截获技术 294

111 Windows网络数据和封包过滤概述 294

1111 Windows网络系统体系结构图 294

1112 用户模式下的网络数据过滤 295

1113 内核模式下的网络数据过滤 296

112 中间层网络驱动PassThru 296

1121 PassThru NDIS中间层驱动简介 296

1122 编译和安装PassThru驱动 297

113 扩展PassThru NDIS IM驱动——添加IOCTL接口 297

1131 扩展之后的PassThru驱动(PassThruEx)概况 297

1132 添加基本的DeviceIoControl接口 298

1133 添加绑定枚举功能 302

1134 添加ADAPT结构的引用计数 307

1135 适配器句柄的打开/关闭函数 308

1136 句柄事件通知 315

1137 查询和设置适配器的OID信息 315

114 扩展PassThru NDIS IM驱动——添加过滤规则 323

1141 需要考虑的事项 323

1142 过滤相关的数据结构 324

1143 过滤列表 326

1144 网络活动状态 327

1145 IOCTL控制代码 328

1146 过滤数据 331

115 核心层过滤实例 339

第12章 Windows网络防火墙开发技术 342

121 防火墙技术概述 342

122 金羽(Phoenix)个人防火墙浅析 343

1221 金羽(Phoenix)个人防火墙简介 343

1222 金羽(Phoenix)个人防火墙总体设计 344

1223 金羽(Phoenix)个人防火墙总体结构 345

123 开发前的准备 345

1231 常量的定义 346

1232 访问规则 348

1233 会话结构 348

1234 文件结构 349

1235 UNICODE支持 355

124 应用层DLL模块 356

1241 DLL工程框架 356

1242 共享数据和IO控制 362

1243 访问控制列表ACL(Access List) 364

1244 查找应用程序访问权限的过程 367

1245 类的接口——检查函数 370

125 核心层SYS模块 373

126 主模块工程 375

1261 I/O控制类 375

1262 主应用程序类 377

1263 主对话框中的属性页 380

1264 主窗口类 381

127 防火墙页面 383

1271 网络访问监视页面 383

1272 应用层过滤规则页面 387

1273 核心层过滤规则页面 397

1274 系统设置页面 403

第13章 IP帮助函数 406

131 IP配置信息 406

1311 获取网络配置信息 406

1312 管理网络接口 408

1313 管理IP地址 412

132 获取网络状态信息 415

1321 获取TCP连接表 415

1322 获取UDP监听表 418

1323 获取IP统计数据 420

133 路由管理 427

1331 获取路由表 427

1332 管理特定路由 431

1333 修改默认网关的例子 432

134 ARP表管理 433

1341 获取ARP表 433

1342 添加ARP入口 434

1343 删除ARP入口 434

1344 打印ARP表的例子 434

135 进程网络活动监视实例 438

1351 获取通信的进程终端 438

1352 Netstate源程序代码 439

第14章 Email协议及其编程 444

141 概述 444

142 电子邮件介绍 445

1421 电子邮件Internet的地址 445

1422 Internet邮件系统 445

1423 电子邮件信头的结构及分析 446

143 SMTP原理 448

1431 SMTP原理分析 448

1432 SMTP工作机制 449

1433 SMTP命令码和工作原理 449

1434 SMTP通信模型 450

1435 SMTP的命令和应答 451

144 POP3协议原理 452

1441 POP3协议简介 452

1442 POP3工作原理 453

1443 POP3命令原始码 454

1444 POP3会话实例 459

145 实例分析与程序设计 460

1451 总界面设计 460

1452 SMTP客户端设计 461

1453 POP3客户端设计 473

DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
网站模板库 » Windows网络与通信程序设计的目录

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情