分享
分销 收藏 举报 申诉 / 62
播放页_导航下方通栏广告

类型孙卫琴网络编程PPT4word版本.ppt

  • 上传人:精****
  • 文档编号:5481106
  • 上传时间:2024-11-11
  • 格式:PPT
  • 页数:62
  • 大小:515.50KB
  • 下载积分:14 金币
  • 播放页_非在线预览资源立即下载上方广告
    配套讲稿:

    如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。

    特殊限制:

    部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。

    关 键  词:
    孙卫琴 网络 编程 PPT4word 版本
    资源描述:
    Java网络编程精解作者:孙卫琴作者:孙卫琴作者:孙卫琴作者:孙卫琴参考书籍:参考书籍:参考书籍:参考书籍:Java技术支持网址:技术支持网址:技术支持网址:技术支持网址:www.javathinker.orgwww.javathinker.org第4章 非阻塞通信参考Java网络编程精解的第4章n4.1 线程阻塞的概念n4.2 java.nio包中的主要类n4.3 服务器编程范例n4.3.1 创建阻塞的EchoServern4.3.2 创建非阻塞的EchoServern4.3.3 在EchoServer中混合用阻塞模式与非阻塞模式n4.4 客户端编程范例n4.4.1 创建阻塞的EchoClientn4.4.2 创建非阻塞的EchoClientn4.4.3 创建非阻塞的PingClient4.1 线程阻塞的概念 n在生活中,最常见的阻塞现象是公路上汽车的堵塞。汽车在公路上快速运行,如果前方交通受阻,就只好停下来等待,等到公路顺畅,才能恢复运行。n线程在运行中也会因为某些原因而阻塞。所有处于阻塞状态的线程的共同特征是:n放弃CPU,暂停运行,只有等到导致阻塞的原因消除,才能恢复运行;或者被其他线程中断,该线程会退出阻塞状态,并且抛出InterruptedException。4.1.1 线程阻塞的原因n导致线程阻塞的原因主要有以下方面:n线程执行了Thread.sleep(int n)方法,线程放弃CPU,睡眠n毫秒,然后恢复运行。n线程要执行一段同步代码,由于无法获得相关的同步锁,只好进入阻塞状态,等到获得了同步锁,才能恢复运行。n线程执行了一个对象的wait()方法,进入阻塞状态,只有等到其他线程执行了该对象的notify()或notifyAll()方法,才可能将其唤醒。n线程执行I/O操作或进行远程通信时,会因为等待相关的资源而进入阻塞状态。4.1.1 线程阻塞的原因n进行远程通信时,在客户程序中,线程在以下情况可能进入阻塞状态:n请求与服务器建立连接时,会进入阻塞状态,直到连接成功。n线程从Socket的输入流读入数据时,如果没有足够的数据,就会进入阻塞状态,直到读到了足够的数据,或者到达输入流的末尾,或者出现了异常,才从输入流的read()方法返回或异常中断。n线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流的write()方法返回或异常中断。n当调用Socket的setSoLinger()方法设置了关闭Socket的延迟时间,那么当线程执行Socket的close()方法时,会进入阻塞状态,直到底层Socket发送完所有剩余数据,或者超过了setSoLinger()方法设置的延迟时间,才从close()方法返回。4.1.1 线程阻塞的原因n在服务器程序中,线程在以下情况可能会进入阻塞状态:n线程执行ServerSocket的accept()方法,等待客户的连接,直到接收到了客户连接,才从accept()方法返回。n线程从Socket的输入流读入数据时,如果输入流没有足够的数据,就会进入阻塞状态。n线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流的write()方法返回或异常中断。4.1.1 线程阻塞的原因n由此可见,无论是在服务器程序还是客户程序中,当通过Socket的输入流和输出流来读写数据时,都可能进入阻塞状态。这种可能出现阻塞的输入和输出操作被称为阻塞I/O。与此对照,如果执行输入和输出操作时,不会发生阻塞,则称为非阻塞I/O。4.1.2 服务器程序用多线程处理阻塞通信的局限 n(1)Java虚拟机会为每个线程分配独立的堆栈空间,工作线程数目越多,系统开销就越大,而且增加了Java虚拟机调度线程的负担,增加了线程之间同步的复杂性,提高了线程死锁的可能性。n(2)工作线程的许多时间都浪费在阻塞I/O操作上,Java虚拟机需要频繁的转让CPU的使用权,使进入阻塞状态的线程放弃CPU,再把CPU分配给处于可运行状态的线程。4.1.2 服务器程序用多线程处理阻塞通信的局限n工作线程并不是越多越好。如图4-2所示,保持适量的工作线程,会提高服务器的并发性能,但是当工作线程的数目到达某个极限,超出了系统的负荷时,反而会降低并发性能,使得多数客户无法快速得到服务器的响应。4.1.3 非阻塞通信的基本思想 n服务器程序只需要一个线程就能同时负责接收客户的连接、接收各个客户发送的数据,以及向各个客户发送响应数据。服务器程序的处理流程如下:while(一直等待,直到有接收连接就绪事件、读就绪事件或写就绪事件发生)/阻塞if(有客户连接)接收客户的连接;/非阻塞if(某个Socket的输入流中有可读数据)从输入流中读数据;/非阻塞if(某个Socket的输出流可以写数据)向输出流写数据;/非阻塞n以上处理流程采用了轮询的工作方式,当某一种操作就绪,就执行该操作,否则就察看是否还有其他就绪的操作可以执行。线程不会因为某一个操作还没有就绪,就进入阻塞状态,一直傻傻的在那里等待这个操作就绪。4.2 java.nio包中的主要类njava.nio包提供了支持非阻塞通信的类,主要包括:nServerSocketChannel:ServerSocket的替代类,支持阻塞通信与非阻塞通信。nSocketChannel:Socket的替代类,支持阻塞通信与非阻塞通信。nSelector:为ServerSocketChannel监控接收连接就绪事件,为SocketChannel监控连接就绪、读就绪和写就绪事件。nSelectionKey:代表ServerSocketChannel以及SocketChannel向Selector注册事件的句柄。当一个SelectionKey对象位于Selector对象的selected-keys集合中,就表示与这个SelectionKey对象相关的事件发生了。4.2 java.nio包中的主要类4.2.1 缓冲区Buffern数据输入和输出往往是比较耗时的操作。缓冲区从两个方面提高I/O操作的效率:n减少实际的物理读写次数。n缓冲区在创建时被分配内存,这块内存区域一直被重用,这可以减少动态分配和回收内存区域的次数。njava.nio包公开了Buffer API,使得Java程序可以直接控制和运用缓冲区。4.2.1 缓冲区Buffer n图4-4显示了Buffer类的层次结构。4.2.1 缓冲区Buffern所有的缓冲区都有以下属性:n容量(capacity):表示该缓冲区可以保存多少数据。n极限(limit):表示缓冲区的当前终点,不能对缓冲区中超过极限的区域进行读写操作。极限是可以修改的,这有利于缓冲区的重用。例如,假定容量为100的缓冲区已经填满了数据,接着程序在重用缓冲区时,仅仅将10个新的数据写入缓冲区中从位置0到10的区域,这时可以将极限设为10,这样就不能读取先前的数据了。极限是一个非负整数,不应该大于容量。n位置(position):表示缓冲区中下一个读写单元的位置,每次读写缓冲区的数据时,都会改变该值,为下一次读写数据作准备。位置是一个非负整数,不应该大于极限。n以上三个属性的关系为:容量=极限=位置=04.2.1 缓冲区Buffern缓冲区提供了用于改变以上三个属性的方法:nclear():把极限设为容量,再把位置设为0。nflip():把极限设为位置,再把位置设为0。nrewind():不改变极限,把位置设为0。4.2.1 缓冲区BuffernBuffer类的remaining()方法返回缓冲区的剩余容量,取值等于极限-位置。Buffer类的compact()方法删除缓冲区内从0到当前位置position的内容,然后把从当前位置position到极限limit的内容拷贝到0到limit-position的区域内,当前位置position和极限limit的取值也做相应的变化,参见图4-6。4.2.1 缓冲区Buffernjava.nio.Buffer类是一个抽象类,不能被实例化。共有8个具体的缓冲区类,其中最基本的缓冲区是ByteBuffer,它存放的数据单元是字节。ByteBuffer类并没有提供公开的构造方法,但是提供了两个获得ByteBuffer实例的静态工厂方法:nallocate(int capacity):返回一个ByteBuffer对象,参数capacity指定缓冲区的容量。ndirectAllocate(int capacity):返回一个ByteBuffer对象,参数capacity指定缓冲区的容量。该方法返回的缓冲区称为直接缓冲区,它与当前操作系统能够更好的耦合,因此能进一步提高I/O操作的速度。但是分配直接缓冲区的系统开销很大,因此只有在缓冲区较大并且长期存在,或者需要经常重用时,才使用这种缓冲区。4.2.1 缓冲区Buffern所有具体缓冲区类都提供了读写缓冲区的方法:nget():相对读。从缓冲区的当前位置读取一个单元的数据,读完后把位置加1。nget(int index):绝对读。从参数index指定的位置读取一个单元的数据。nput():相对写。向缓冲区的当前位置写入一个单元的数据,写完后把位置加1。nput(int index):绝对写。向参数index指定的位置写入一个单元的数据。4.2.2 字符编码CharsetnCharset类提供了编码与解码的方法:nByteBuffer encode(String str):对参数str指定的字符串进行编码,把得到的字节序列存放在一个ByteBuffer对象中,并将其返回。nByteBuffer encode(CharBuffer cb):对参数cb指定的字符缓冲区中的字符进行编码,把得到的字节序列存放在一个ByteBuffer对象中,并将其返回。nCharBuffer decode(ByteBuffer bb):把参数bb指定的ByteBuffer中的字节序列进行解码,把得到的字符序列存放在一个CharBuffer对象中,并将其返回。4.2.2 字符编码CharsetnCharset类的静态forName(String encode)方法返回一个Charset对象,它代表参数encode指定的编码类型。n例如以下代码创建了一个代表“GBK”编码的Charset对象:Charset charset=Charset.forName(GBK);4.2.3 通道Channeln通道Channel用来连接缓冲区与数据源或数据汇(即数据目的地)。如图4-8所示,数据源的数据经过通道到达缓冲区,缓冲区的数据经过通道到达数据汇。4.2.3 通道Channel 4.2.3 通道Channelnjava.nio.channels.Channel接口只声明了两个方法:nclose():关闭通道。nisOpen():判断通道是否打开。n通道在创建时被打开,一旦关闭通道,就不能重新打开它。4.2.3 通道ChannelnReadableByteChannel接口:声明了read(ByteBuffer dst)方法,该方法把数据源的数据读入到参数指定的ByteBuffer缓冲区中。nWritableByteChannel接口:声明了write(ByteBuffer src)方法,该方法把参数指定的ByteBuffer缓冲区中的数据写到数据汇中。nScatteringByteChannel接口:扩展了ReadableByteChannel接口,允许分散的读取数据。nGatheringByteChannel接口:扩展了WritableByteChannel接口,允许集中的写入数据。nFileChannel类:是Channel接口的实现类,代表一个与文件相连的通道。该类实现了ByteChannel、ScatteringByteChannel和GatheringByteChannel接口,支持读操作、写操作、分散读操作和集中写操作。nSelectableChanne类:也是一种通道,它不仅支持阻塞的I/O操作,还支持非阻塞的I/O操作。4.2.3 通道ChannelnSelectableChannel有两个子类:nServerSocketChannel类nSocketChannel类:SocketChannel还实现了ByteChannel接口,具有read(ByteBuffer dst)和write(ByteBuffer src)方法。4.2.4 SelectableChannel类nSelectableChannel是一种支持阻塞I/O和非阻塞I/O的通道。在非阻塞模式下,读写数据不会阻塞,并且SelectableChannel可以向Selector注册读就绪和写就绪等事件。Selector负责监控这些事件,等到事件发生时,比如发生了读就绪事件,SelectableChannel就可以执行读操作了。4.2.4 SelectableChannel类nSelectableChannel的主要方法如下。npublic SelectableChannel configureBlocking(boolean block)throws IOExceptionnpublic SelectionKey register(Selector sel,int ops)throws ClosedChannelExceptionnpublic SelectionKey register(Selector sel,int ops,Object attachment)throws ClosedChannelException 4.2.5 ServerSocketChannel类nServerSocketChannel从SelectableChannel中继承了configureBlocking()和register()方法。ServerSocketChannel是ServerSocket的替代类,也具有负责接收客户连接的accept()方法。ServerSocketChannel并没有public类型的构造方法,必须通过它的静态方法open()来创建ServerSocketChannel对象。每个ServerSocketChannel对象都与一个ServerSocket对象关联。ServerSocketChannel的socket()方法返回与它关联的ServerSocket对象。n可通过以下方式把服务器进程绑定到一个本地端口:serverSocketChannel.socket().bind(port);4.2.5 ServerSocketChannel类nServerSocketChannel的主要方法如下。npublic static ServerSocketChannel open()throws IOExceptionnpublic SocketChannel accept()throws IOExceptionnpublic final int validOps()npublic ServerSocket socket()4.2.6 SocketChannel类nSocketChannel可看作是Socket的替代类,但它比Socket具有更多的功能。SocketChannel不仅从SelectableChannel父类中继承了configureBlocking()和register()方法,而且实现了ByteChannel接口,因此具有用于读写数据的read(ByteBuffer dst)和write(ByteBuffer src)方法。SocketChannel没有public类型的构造方法,必须通过它的静态方法open()来创建SocketChannel对象。4.2.6 SocketChannel类nSocketChannel的主要方法如下。npublic static SocketChannel open()throws IOException npublic static SocketChannel open(SocketAddress remote)throws IOExceptionnpublic final int validOps()npublic Socket socket()npublic boolean isConnected()npublic boolean isConnectionPending()npublic boolean connect(SocketAddress remote)throws IOExceptionnpublic boolean finishConnect()throws IOExceptionnpublic int read(ByteBuffer dst)throws IOExceptionnpublic int write(ByteBuffer src)throws IOException4.2.7 Selector类n只要ServerSocketChannel以及SocketChannel向Selector注册了特定的事件,Selector就会监控这些事件是否发生。SelectableChannel的register()方法负责注册事件,该方法返回一个SelectionKey对象,该对象是用于跟踪这些被注册事件的句柄。4.2.7 Selector类n一个Selector对象中会包含三种类型的SelectionKey的集合:nall-keys集合:当前所有向Selector注册的SelectionKey的集合,Selector的keys()方法返回该集合。nselected-keys集合:相关事件已经被Selector捕获的SelectionKey的集合。Selector的selectedKeys()方法返回该集合。ncancelled-keys集合:已经被取消的SelectionKey的集合。Selector没有提供访问这种集合的方法。4.2.7 Selector类nSelector类的主要方法如下。npublic static Selector open()throws IOExceptionnpublic boolean isOpen()npublic Set keys()npublic int selectNow()throws IOExceptionnpublic int select()throws IOExceptionnpublic int select(long timeout)throws IOExceptionnpublic Selector wakeup()npublic void close()throws IOException4.2.8 SelectionKey类nServerSocketChannel或SocketChannel通过register()方法向Selector注册事件时,register()方法会创建一个SelectionKey对象,这个SelectionKey对象是用来跟踪注册事件的句柄。n在SelectionKey对象的有效期间,Selector会一直监控与SelectionKey对象相关的事件,如果事件发生,就会把SelectionKey对象加入到selected-keys集合中。n在以下情况,SelectionKey对象会失效,这意味着Selector再也不会监控与它相关的事件:n(1)程序调用SelectionKey的cancel()方法。n(2)关闭与SelectionKey关联的Channel。n(3)与SelectionKey关联的Selector被关闭。4.2.8 SelectionKey类n在SelectionKey中定义了四种事件,分别用4个int类型的常量来表示:nSelectionKey.OP_ACCEPT:接收连接就绪事件,表示服务器监听到了客户连接,服务器可以接收这个连接了。常量值为16nSelectionKey.OP_CONNECT:连接就绪事件,表示客户与服务器的连接已经建立成功。常量值为8。nSelectionKey.OP_READ:读就绪事件,表示通道中已经有了可读数据,可以执行读操作了。常量值为1。nSelectionKey.OP_WRITE:写就绪事件,表示已经可以向通道写数据了。常量值为4。n以上常量分别占居不同的二进制位,因此可以通过二进制的或运算“|”,来将它们进行任意组合。4.2.8 SelectionKey类n一个SelectionKey对象中包含两种类型的事件:n所有感兴趣的事件:SelectionKey的interestOps()方法返回所有感兴趣的事件,例如假定返回值为SelectionKey.OP_WRITE|SelectionKey.OP_READ,就表示这个SelectionKey对读就绪和写就绪事件感兴趣。与之关联的Selector对象会负责监控这些事件。当通过SelectableChannel的register()方法注册事件时,可以在参数中指定SelectionKey感兴趣的事件,例如以下代码表明新建的SelectionKey对连接就绪和读就绪事件感兴趣:SelectionKey key=socketChannel.register(selector,SelectionKey.OP_CONNECT|SelectionKey.OP_READ);SelectionKey的interestOps(int ops)方法用于为SelectionKey对象增加一个感兴 趣的事件。例如以下代码使得SelectionKey增加了一个感兴趣的事件:key.interestOps(SelectionKey.OP_WRITE);n所有已经发生的事件:SelectionKey的readyOps()方法返回所有已经发生的事件,例如假定返回值为SelectionKey.OP_WRITE|SelectionKey.OP_READ,表示读就绪和写就绪事件已经发生了,这意味着与之关联的SocketChannel对象可以进行读操作和写操作了。4.2.8 SelectionKey类4.2.8 SelectionKey类nSelectionKey的主要方法如下。npublic SelectableChannel channel()npublic Selector selector()npublic boolean isValid()npublic void cancel()npublic int interestOps()npublic SelectionKey interestOps(int ops)npublic int readyOps()npublic final boolean isReadable()npublic final boolean isWritable()npublic final boolean isConnectable()npublic final boolean isAcceptable()npublic final Object attach(Object ob)npublic final Object attachment()4.3 服务器编程范例n本节介绍如何用java.nio包中的类来创建服务器EchoServer,本节提供了三种实现方式:n4.3.1节的例程4-1:采用阻塞模式,用线程池中的工作线程处理每个客户连接。n4.3.2节的例程4-2:采用非阻塞模式,单个线程同时负责接收多个客户连接,以及与多个客户交换数据的任务。n4.3.3节的例程4-3:由一个线程负责接收多个客户连接,采用阻塞模式;由另一个线程负责与多个客户交换数据,采用非阻塞模式。4.3.1 创建阻塞的EchoServern当ServerSocketChannel与SocketChannel采用默认的阻塞模式时,为了同时处理多个客户的连接,必须使用多个线程。在例程4-1的EchoServer类中,利用java.util.concurrent包中提供的线程池ExecutorService来处理与客户的连接。nEchoServer类的构造方法负责创建线程池,启动服务器,把它绑定到一个本地端口。EchoServer类的service()方法负责接收客户的连接。每接收到一个客户连接,就把它交给线程池来处理,线程池取出一个空闲的线程,来执行Handler对象的run()方法。Handler类的handle()方法负责与客户通信。该方法先获得与SocketChannel关联的Socket对象,然后从Socket对象中得到输入流与输出流,再接收和发送数据。4.3.2 创建非阻塞的EchoServern在非阻塞模式下,EchoServer只需要启动一个主线程,就能同时处理三件事:n(1)接收客户的连接。n(2)接收客户发送的数据。n(3)向客户发回响应数据。4.3.2 创建非阻塞的EchoServernEchoServer委托Selector来负责监控接收连接就绪事件、读就绪事件和写就绪事件,如果有特定事件发生,就处理该事件。nEchoServer类的构造方法负责启动服务器,把它绑定到一个本地端口,代码如下:/创建一个Selector对象selector=Selector.open();/创建一个ServerSocketChannel对象serverSocketChannel=ServerSocketChannel.open();/使得在同一个主机上关闭了服务器程序,紧接着再启动该服务器程序时,/可以顺利绑定到相同的端口serverSocketChannel.socket().setReuseAddress(true);/使ServerSocketChannel工作于非阻塞模式serverSocketChannel.configureBlocking(false);/把服务器进程与一个本地端口绑定serverSocketChannel.socket().bind(new InetSocketAddress(port);4.3.2 创建非阻塞的EchoServernEchoServer类的service()方法负责处理本节开头所说的三件事,体现其主要流程的代码如下:1.public void service()throws IOException2.serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);3.while(selector.select()0)/第一层while循环4.Set readyKeys=selector.selectedKeys();/获得Selector的selected-keys集合5.Iterator it=readyKeys.iterator();6.while(it.hasNext()/第二层while循环7.SelectionKey key=null;8.try /处理SelectionKey9.key=(SelectionKey)it.next();/取出一个SelectionKey10.it.remove();/把SelectionKey从Selector的selected-key集合中删除11.if(key.isAcceptable()处理接收连接就绪事件;12.if(key.isReadable()处理读就绪事件;13.if(key.isWritable()处理写就绪事件;14.catch(IOException e)4.3.2 创建非阻塞的EchoServer14.catch(IOException e)15.e.printStackTrace();16.try17.if(key!=null)18./使这个SelectionKey失效,19./使得Selector不再监控这个SelectionKey感兴趣的事件20.key.cancel();21.key.channel().close();/关闭与这个SelectionKey关联的SocketChannel22.23.catch(Exception ex)e.printStackTrace();24.25./#while26./#while27.4.3.3 在EchoServer中混合用阻塞模式与非阻塞模式n在本章4.3.2节的例程4-2中,EchoServer的ServerSocketChannel以及SocketChannel都被设置为非阻塞模式,这使得接收连接、接收数据和发送数据的操作都采用非阻塞模式,EchoServer采用一个线程同时完成这些操作。假如有许多客户请求连接,可以把接收客户连接的操作单独由一个线程完成,把接收数据和发送数据的操作由另一个线程完成,这可以提高服务器的并发性能。n负责接收客户连接的线程按照阻塞模式工作,如果收到客户连接,就向Selector注册读就绪和写就绪事件,否则进入阻塞状态,直到接收到了客户的连接。负责接收数据和发送数据的线程按照非阻塞模式工作,只有在读就绪或写就绪事件发生时,才执行相应的接收数据和发送数据操作。4.3.3 在EchoServer中混合用阻塞模式与非阻塞模式n在EchoServer类的main()方法中,定义了一个匿名线程(暂且称它为Accept线程),它负责执行EchoServer的accept()方法。执行main()方法的主线程启动了Accept线程后,主线程就开始执行EchoServer的service()方法。因此当EchoServer启动后,共有两个线程在工作,Accept线程负责接收客户连接,主线程负责接收和发送数据:public static void main(String args)throws Exception final EchoServer server=new EchoServer();Thread accept=new Thread()/定义Accept线程 public void run()server.accept();accept.start();/启动Accept线程 server.service();/主线程执行service()方法4.4 客户端编程范例n本节介绍如何用java.nio包中的类来创建客户程序EchoClient,本节提供了两种实现方式:n4.4.1节的例程4-4:采用阻塞模式,单线程。n4.4.2节的例程4-5:采用非阻塞模式,单线程。n4.4.3节还介绍了一个PingClient例子,它能同时连接多个服务器,计算建立连接所花的时间。PingClient仅使用了一个线程,它能在非阻塞模式下同时与多个服务器建立连接。4.4.1 创建阻塞的EchoClientn客户程序一般不需要同时建立与服务器的多个连接,因此用一个线程,按照阻塞模式运行就能满足需求。本书第1章的1.5.2节的例程1-3的EchoClient类是通过创建Socket来建立与服务器的连接的,以下例程4-4的EchoClient类通过创建SocketChannel来与服务器连接,这个SocketChannel采用默认的阻塞模式。n在EchoClient类中,调用socketChannel.connect(isa)方法连接远程服务器,该方法在阻塞模式下运行时,将等到与远程服务器的连接建立成功才返回。在EchoClient类的talk()方法中,通过socketChannel.socket()方法获得与SocketChannel关联的Socket对象,然后从这个Socket中获得输出流与输入流,再一行行的发送和接受数据。4.4.2 创建非阻塞的EchoClientn对于客户与服务器之间的通信,按照它们收发数据的协调程度来区分,可分为同步通信和异步通信:n同步通信是指甲方向乙方发送了一批数据后,必须等接收到了乙方的响应数据后,再发送下一批数据。n异步通信是指发送数据和接收数据的操作互不干扰,各自独立进行。n值得注意的是,通信的两端并不要求都采用同样的通信方式,一方采用同步通信方式时,另一方可以采用异步通信方式。n同步通信要求一个I/O操作完成之后,才能完成下一个I/O操作,用阻塞模式更容易实现它。异步通信允许发送数据和接收数据的操作各自独立进行,用非阻塞模式更容易实现它。4.4.2 创建非阻塞的EchoClientn本节例程4-5的EchoClient类利用非阻塞模式来实现异步通信。在EchoClient类中,定义了两个ByteBuffer:sendBuffer和receiveBuffer。EchoClient把用户向控制台输入的数据存放到sendBuffer中,并且把sendBuffer中的数据发送给远程服务器;EchoClient把从远程服务器接收到的数据存放在receiveBuffer中,并且把receiveBuffer中的数据打印到控制台。图4-16显示了这两个Buffer的作用。4.4.3 创建非阻塞的PingClientn当客户程序只需与服务器建立一个连接,用阻塞模式建立连接就可以了,这可以简化编程。如果客户程序需要与服务器同时建立多个连接,由于每个连接的建立都需要耗费一定时间,可采用非阻塞模式来建立连接。n例程4-6的PingClient类不断接收用户输入的域名(即网络上主机的名字),然后与这个主机上的80端口建立连接,最后打印建立连接所花费的时间。如果程序无法连接到指定的主机,就打印相关错误信息。如果用户输入“bye”,就结束程序。4.4.3 创建非阻塞的PingClientnPingClient类中定义了两个队列:targets队列和finishedTargets队列,这些队列中都存放Target对象:ntargets队列中存放用户新提交的任务nfinishedTargets队列中存放已经处理完毕的任务4.4.3 创建非阻塞的PingClientnPingClient类一共使用了三个线程:n主线程:主要负责接收用户输入的数据,然后生成Target对象,把它加入到targets队列中。这些操作由receiveTarget()方法实现。nConnector线程:负责从targets队列中取出Target对象,然后向Selector注册连接就绪事件,这些操作由registerTargets()方法实现。Connector线程还负责向Selector查询已经连接就绪的事件,然后把相应的Target对象加入到finishedTargets队列中,这些操作由processSelectedKeys()方法实现。Connector线程由Connector类定义。nPrinter线程:负责从finishedTargets队列中取出Target对象,然后调用它的show()方法打印任务的执行结果。这些操作由printFinishedTargets()方法实现。Printer线程由Printer类定义。练习题1n问题:在服务器程序中,线程在哪些情况可能会进入阻塞状态?问题:在服务器程序中,线程在哪些情况可能会进入阻塞状态?n选项选项:na)线程执行线程执行Socket的的getInputStream()方法获得输入流。方法获得输入流。nb)线程执行线程执行Socket的的getOutputStream()方法获得输出流。方法获得输出流。nc)线程执行线程执行ServerSocket的的accept()方法。方法。nd)线程从线程从Socket的输入流读入数据。的输入流读入数据。ne)线程向线程向Socket的输出流写一批数据。的输出流写一批数据。n答案答案:c,d,e练习题2n问题:问题:ServerSocketChannel可能发生哪些事件可能发生哪些事件?n选项选项:na)SelectionKey.OP_ACCEPT:接收连接就绪事件:接收连接就绪事件nb)SelectionKey.OP_CONNECT:
    展开阅读全文
    提示  咨信网温馨提示:
    1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
    2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
    3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
    4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
    5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
    6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

    开通VIP折扣优惠下载文档

    自信AI创作助手
    关于本文
    本文标题:孙卫琴网络编程PPT4word版本.ppt
    链接地址:https://www.zixin.com.cn/doc/5481106.html
    页脚通栏广告

    Copyright ©2010-2026   All Rights Reserved  宁波自信网络信息技术有限公司 版权所有   |  客服电话:0574-28810668    微信客服:咨信网客服    投诉电话:18658249818   

    违法和不良信息举报邮箱:help@zixin.com.cn    文档合作和网站合作邮箱:fuwu@zixin.com.cn    意见反馈和侵权处理邮箱:1219186828@qq.com   | 证照中心

    12321jubao.png12321网络举报中心 电话:010-12321  jubao.png中国互联网举报中心 电话:12377   gongan.png浙公网安备33021202000488号  icp.png浙ICP备2021020529号-1 浙B2-20240490   


    关注我们 :微信公众号  抖音  微博  LOFTER               

    自信网络  |  ZixinNetwork