《Java网络编程(5).pdf》由会员分享,可在线阅读,更多相关《Java网络编程(5).pdf(7页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Java网络编程(5)作者:刘晓华发文时间:2004.11.22 使用 Java NIO 提高服务端程序的性能在前面的章节里,我们讨论了Java NIO 的基本概念,在这一节里,我们将结合具体的 Java Socket编程,讨论使用NIO 提高服务端程序的性能的问题。Java NIO 增加了新的SocketChannel、ServerSocketChannel等类来提供对构建高性能的服务端程序的支持。SocketChannel、ServerSocketChannel能够在非阻塞的模式下工作,它们都是 selectable的类。在构建服务器或者中间件时,推荐使用 Java NIO。在传统的网络编
2、程中,我们通常使用一个专用线程(Thread)来处理一个Socket连接,通过使用NIO,一个或者很少几个Socket线程就可以处理成千上万个活动的Socket 连接。通常情况下,通过ServerSocketChannel.open()获得一个 ServerSocketChannel的实例,通过 SocketChannel.open或者 serverSocketChannel.accept()获得一个SocketChannel 实例。要使ServerSocketChannel或者 SocketChannel在非阻塞的模式下操作,可以调用 serverSocketChannel.configur
3、eBlocking(false);或者 socketChannel.configureBlocking(false);语句来达到目的。通常情况下,服务端可以使用非阻塞的ServerSocketChannel,这样,服务端的程序就可以更容易地同时处理多个socket 线程。下面我们来看一个综合例子,这个例子使用了ServerSocketChannel、SocketChannel开发了一个非阻塞的、能处理多线程的Echo 服务端程序,见示例12-14。【程序源代码】1/=Program Discription=2/程序名称:示例 12-14:SocketChannelDemo.java 3/程序目
4、的:学习 Java NIO#SocketChannel 4/=5 6 7 import java.nio.ByteBuffer;8 import java.nio.channels.ServerSocketChannel;9 import java.nio.channels.SocketChannel;10 import java.nio.channels.Selector;11 import java.nio.channels.SelectionKey;12 import java.nio.channels.SelectableChannel;13 14 import .Socket;15
5、import .ServerSocket;16 import .InetSocketAddress;17 import java.util.Iterator;18 19 public class SocketChannelDemo 20 21 22 public static int PORT_NUMBER=23;/监听端口23 ServerSocketChannel serverChannel;24 ServerSocket serverSocket;25 Selector selector;26 private ByteBuffer buffer=ByteBuffer.allocateDi
6、rect(1024);27 28 public static void main(String args)29 throws Exception 30 31 SocketChannelDemo server=new SocketChannelDemo();32 server.init(args);33 server.startWork();34 35 36 37 public void init(String argv)throws Exception 38 39 int port=PORT_NUMBER;40 41 if(argv.length 0)42 port=Integer.parse
7、Int(argv 0);43 44 45 System.out.println(Listening on port +port);46 47/分配一个 ServerSocketChannel 48 serverChannel=ServerSocketChannel.open();49/从 ServerSocketChannel 里获得一个对应的 Socket 50 serverSocket=serverChannel.socket();51/生成一个 Selector 52 selector=Selector.open();53 54/把 Socket 绑定到端口上55 serverSocke
8、t.bind(new InetSocketAddress(port);56/serverChannel为非 bolck 57 serverChannel.configureBlocking(false);58 59/通过 Selector注册 ServerSocetChannel 60 serverChannel.register(selector,SelectionKey.OP_ACCEPT);61 62 63 64 public void startWork()throws Exception 65 66 67 while(true)68 69 int n=selector.select(
9、);/获得IO 准备就绪的 channel 数量70 71 if(n=0)72 continue;/没有channel 准备就绪,继续执行73 74 75/用一个 iterator返回 Selector的 selectedkeys 76 Iterator it=selector.selectedKeys().iterator();77 78/处理每一个 SelectionKey 79 while(it.hasNext()80 SelectionKey key=(SelectionKey)it.next();81 82/判断是否有新的连接到达83 if(key.isAcceptable()84/
10、返回 SelectionKey的ServerSocketChannel 85 ServerSocketChannel server=(ServerSocketChannel)key.channel();86 SocketChannel channel=server.accept();87 88 registerChannel(selector,channel,89 SelectionKey.OP_READ);90 91 doWork(channel);92 93 94/判断是否有数据在此channel 里需要读取95 if(key.isReadable()96 97 processData(k
11、ey);98 99 100 101/删除 selectedkeys 102 it.remove();103 104 105 106 protected void registerChannel(Selector selector,107 SelectableChannel channel,int ops)108 throws Exception 109 110 if(channel=null)111 return;112 113 114 115 channel.configureBlocking(false);116 117 channel.register(selector,ops);118
12、 119 120 /处理接收的数据121 protected void processData(SelectionKey key)122 throws Exception 123 124 125 126 SocketChannel socketChannel=(SocketChannel)key.channel();127 int count;128 129 buffer.clear();/清空buffer 130 131/读取所有的数据132 while(count=socketChannel.read(buffer)0)133 buffer.flip();134 135/send the
13、data,dont assume it goes all at once 136 while(buffer.hasRemaining()137 138/如果收到回车键,则在返回的字符前增加 echo$字样139 if(buffer.get()=(char)13)140 141 buffer.clear();142 buffer.put(echo$.getBytes();143 buffer.flip();144 145 146 socketChannel.write(buffer);/在 Socket 里写数据147 148 149 buffer.clear();/清空buffer 150 1
14、51 152 if(count 0)153/count0,说明已经读取完毕154 socketChannel.close();155 156 157 158 159 private void doWork(SocketChannel channel)throws Exception 160 161 buffer.clear();162 buffer.put(Hello,I am working,please input some thing,and i will echo to you!rnecho$.getBytes();163 buffer.flip();164 channel.write
15、(buffer);165 166 167 使用:运行此程序,然后在控制台输入命令telnet localhost 23。【程序输出结果】如图12-1 所示。图 12-1 输出结果【程序注解】关于程序的解释已经包含在程序里面了,在这里我们总结以下使用ServerSocket Channel 开发服务端程序的过程:(1)分配一个ServerSocketChannel。(2)从 ServerSocketChannel里获得一个对应的ServerSocket。(3)生成一个Selector 实例。(4)把 ServerSocket绑定到端口上。(5)设置 ServerSocketChannel为非 b
16、lock 模式(可选)。(6)在 Selector 里注册 ServerSocetChannel。(7)用一个无限循环语句始终查看Selector 里是否有 IO 准备就绪的channel。如果有,就执行对应的处理,如果没有,继续循环。小 结在本章我们主要介绍了Java中的网络编程。Java一开始就是一种网络编程语言,到后来才应用到各个方面,所以在Java中进行网络编程远比在C/C+中方便。我们介绍了几个在网络编程中很重要的类,如 InetAddress、URL、URLConnection、Socket、ServerSocket、DatagramSocket、DatagramPacket、MulticastSocket 等。这些类包含了进行基本网络编程的所有内容。要熟练地应用这些类,关键还是要多多练习。基于套接字的编程基本上是客户/服务器模式,我们具体介绍了编写这种模式的步骤。在实例方面,我们给出了一个基于TCP 的套接字客户/服务器程序,与此相对应,还给出了基于UDP 的客户/服务器程序。两者的模式是很相似的,其实这也就是编写客户/服务器程序的一般模式。(T111)本文选自飞思图书精通Java核心技术