Java-NIO非阻塞服務器示例_第1頁
Java-NIO非阻塞服務器示例_第2頁
Java-NIO非阻塞服務器示例_第3頁
Java-NIO非阻塞服務器示例_第4頁
Java-NIO非阻塞服務器示例_第5頁
已閱讀5頁,還剩3頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、Java NIO非阻塞服務器示例姓名:鄧以克 網名:phinecos(洞庭散人) MSN: 出處:本文版權歸作者所有,歡迎傳閱,但請保留此段聲明。 以前一直用的是“ervery thread per connection”的服務器端模式,今天試了下NIO非阻塞模式的服務器。 不過java不能實現I/O完成端口模型,這點很遺憾package com.vista.Server;import java.io.IOException;import .InetSocketAddress;import .ServerSocket;import java.nio.ByteBuffer;import java

2、.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.Iterator;import java.util.LinkedList;import java.util.Set;public class SelectorServer private static int DEFAULT_SERVERPORT = 6018;/默認端口 p

3、rivate static int DEFAULT_BUFFERSIZE = 1024;/默認緩沖區(qū)大小為1024字節(jié) private ServerSocketChannel channel; private LinkedList<SocketChannel> clients; private Selector readSelector; private ByteBuffer buffer;/字節(jié)緩沖區(qū) private int port; public SelectorServer(int port) throws IOException this.port = port; thi

4、s.clients = new LinkedList<SocketChannel>(); this.channel = null; this.readSelector = Selector.open();/打開選擇器 this.buffer = ByteBuffer.allocate(DEFAULT_BUFFERSIZE); / 服務器程序在服務循環(huán)中調用sericeClients()方法為已接受的客戶服務 public void serviceClients()throws IOException Set keys; Iterator it; SelectionKey key;

5、SocketChannel client; / 在readSelector上調用select()方法,參數1代表如果調用select的時候 那么阻塞最多1秒鐘等待可用的客戶端連接 if(readSelector.select(1) > 0) keys = readSelector.selectedKeys(); / 取得代表端通道的鍵集合 it = keys.iterator(); / 遍歷,為每一個客戶服務 while(it.hasNext() key = (SelectionKey)it.next(); if(key.isReadable() / 如果通道可讀,那么讀此通道到buff

6、er中 int bytes; client = (SocketChannel)key.channel();/ 取得鍵對應的通道 buffer.clear(); / 清空緩沖區(qū)中的內容,設置好position,limit,準備接受數據 bytes = client.read(buffer); / 從通道中讀數據到緩沖中,返回讀取得字節(jié)數 if(bytes >= 0) buffer.flip(); / 準備將緩沖中的數據寫回到通道中 client.write(buffer); / 數據寫回到通道中 else if(bytes < 0) / 如果返回小于零的值代表讀到了流的末尾 clie

7、nts.remove(client); / 通道關閉時,選擇鍵也被取消 client.close(); public void registerClient(SocketChannel client) throws IOException / 配置和注冊代表客戶連接的通道對象 client.configureBlocking(false); / 設置此通道使用非阻塞模式 client.register(readSelector, SelectionKey.OP_READ); / 將這個通道注冊到選擇器上 clients.add(client); /保存這個通道對象 public void li

8、sten() throws IOException /服務器開始監(jiān)聽端口,提供服務 ServerSocket socket; SocketChannel client; channel = ServerSocketChannel.open(); / 打開通道 socket = channel.socket(); /得到與通到相關的socket對象 socket.bind(new InetSocketAddress(port), 10); /將scoket榜定在制定的端口上 /配置通到使用非阻塞模式,在非阻塞模式下,可以編寫多道程序同時避免使用復雜的多線程 channel.configureBl

9、ocking(false); try while(true) / 與通常的程序不同,這里使用channel.accpet()接受客戶端連接請求,而不是在socket對象上調用accept(),這里在調用accept()方法時如果通道配置為非阻塞模式,那么accept()方法立即返回null,并不阻塞 client = channel.accept(); if(client != null) registerClient(client); / 注冊客戶信息 serviceClients(); / 為以連接的客戶服務 finally socket.close(); / 關閉socket,關閉soc

10、ket會同時關閉與此socket關聯(lián)的通道 public static void main(String args) throws IOException System.out.println("服務器啟動"); SelectorServer server = new SelectorServer(SelectorServer.DEFAULT_SERVERPORT); server.listen(); /服務器開始監(jiān)聽端口,提供服務 修改版本: package com.vista.Server;import java.io.BufferedWriter;import jav

11、a.io.;import java.io.IOException;import java.io.OutputStreamWriter;import java.io.PrintWriter;import .InetSocketAddress;import .ServerSocket;import java.nio.ByteBuffer;import java.nio.CharBuffer;import java.nio.channels.;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import

12、java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.nio.charset.Charset;import java.nio.charset.CharsetDecoder;import java.util.Iterator;import java.util.LinkedList;import java.util.Set;public class SelectorServer private static int DEFAULT_SERVERPORT = 6018;/默認端

13、口 private static int DEFAULT_BUFFERSIZE = 1024;/默認緩沖區(qū)大小為1024字節(jié) private static String DEFAULT_CHARSET = "GB2312"/默認碼集 private static String DEFAULT_ = "big" private ServerSocketChannel channel; private LinkedList<SocketChannel> clients; private Selector selector;/選擇器 private

14、 ByteBuffer buffer;/字節(jié)緩沖區(qū) private int port; private Charset charset;/字符集 private CharsetDecoder decoder;/解碼器 public SelectorServer(int port) throws IOException this.port = port; this.clients = new LinkedList<SocketChannel>(); this.channel = null; this.selector = Selector.open();/打開選擇器 this.buf

15、fer = ByteBuffer.allocate(DEFAULT_BUFFERSIZE); this.charset = Charset.forName(DEFAULT_CHARSET); this.decoder = this.charset.newDecoder(); private class HandleClient private String strGreeting = "welcome to VistaQQ" public HandleClient() throws IOException public String readBlock() /讀塊數據 re

16、turn this.strGreeting; public void close() protected void handleKey(SelectionKey key) throws IOException /處理事件 if (key.isAcceptable() / 接收請求 ServerSocketChannel server = (ServerSocketChannel) key.channel();/取出對應的服務器通道 SocketChannel channel = server.accept(); channel.configureBlocking(false); channel

17、.register(selector, SelectionKey.OP_READ);/客戶socket通道注冊讀操作 else if (key.isReadable() / 讀信息 SocketChannel channel = (SocketChannel) key.channel(); int count = channel.read(this.buffer); if (count > 0) this.buffer.flip(); CharBuffer charBuffer = decoder.decode(this.buffer); System.out.println("

18、;Client >>" + charBuffer.toString(); SelectionKey wKey = channel.register(selector, SelectionKey.OP_WRITE);/為客戶sockt通道注冊寫操作 wKey.attach(new HandleClient(); else /客戶已經斷開 channel.close(); this.buffer.clear();/清空緩沖區(qū) else if (key.isWritable() / 寫事件 SocketChannel channel = (SocketChannel) key.

19、channel(); HandleClient handle = (HandleClient) key.attachment();/取出處理者 ByteBuffer block = ByteBuffer.wrap(handle.readBlock().getBytes(); channel.write(block); / channel.socket().getInputStream().(block);/ PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(/ channel.socket()

20、.getOutputStream(), true);/ out.write(block.toString(); public void listen() throws IOException /服務器開始監(jiān)聽端口,提供服務 ServerSocket socket; channel = ServerSocketChannel.open(); / 打開通道 socket = channel.socket(); /得到與通到相關的socket對象 socket.bind(new InetSocketAddress(port); /將scoket榜定在制定的端口上 /配置通到使用非阻塞模式,在非阻塞模式下,可以編寫多道程序同時避免使用復雜的多線程 ch

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論