




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、Java NIO非阻塞服務器示例姓名:鄧以克 網(wǎng)名:phinecos(洞庭散人) MSN: 出處:本文版權(quán)歸作者所有,歡迎傳閱,但請保留此段聲明。 以前一直用的是“ervery thread per connection”的服務器端模式,今天試了下NIO非阻塞模式的服務器。 不過java不能實現(xiàn)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)中調(diào)用sericeClients()方法為已接受的客戶服務 public void serviceClients()throws IOException Set keys; Iterator it; SelectionKey key;
5、SocketChannel client; / 在readSelector上調(diào)用select()方法,參數(shù)1代表如果調(diào)用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ū)中的內(nèi)容,設置好position,limit,準備接受數(shù)據(jù) bytes = client.read(buffer); / 從通道中讀數(shù)據(jù)到緩沖中,返回讀取得字節(jié)數(shù) if(bytes >= 0) buffer.flip(); / 準備將緩沖中的數(shù)據(jù)寫回到通道中 client.write(buffer); / 數(shù)據(jù)寫回到通道中 else if(bytes < 0) / 如果返回小于零的值代表讀到了流的末尾 clie
7、nts.remove(client); / 通道關(guān)閉時,選擇鍵也被取消 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(); /得到與通到相關(guān)的socket對象 socket.bind(new InetSocketAddress(port), 10); /將scoket榜定在制定的端口上 /配置通到使用非阻塞模式,在非阻塞模式下,可以編寫多道程序同時避免使用復雜的多線程 channel.configureBl
9、ocking(false); try while(true) / 與通常的程序不同,這里使用channel.accpet()接受客戶端連接請求,而不是在socket對象上調(diào)用accept(),這里在調(diào)用accept()方法時如果通道配置為非阻塞模式,那么accept()方法立即返回null,并不阻塞 client = channel.accept(); if(client != null) registerClient(client); / 注冊客戶信息 serviceClients(); / 為以連接的客戶服務 finally socket.close(); / 關(guān)閉socket,關(guān)閉soc
10、ket會同時關(guān)閉與此socket關(guān)聯(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() /讀塊數(shù)據(jù) 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 /客戶已經(jīng)斷開 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(); /得到與通到相關(guān)的socket對象 socket.bind(new InetSocketAddress(port); /將scoket榜定在制定的端口上 /配置通到使用非阻塞模式,在非阻塞模式下,可以編寫多道程序同時避免使用復雜的多線程 ch
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025學年部編版小學二年級語文上冊教學計劃
- 2025年神經(jīng)內(nèi)科護理團隊建設計劃
- 部編版四年級語文上冊教學內(nèi)容調(diào)整計劃
- 人教版初中九年級下學期音樂教研組工作計劃
- 咸陽市實驗中學2025屆九年級下學期中考四模數(shù)學試卷(含解析)
- 2025年幼兒園后勤工作總結(jié)及秋季計劃
- 八年級下冊歷史教學創(chuàng)新計劃
- “青藍工程”校企合作教師指導計劃
- 人教版數(shù)學七年級下冊備課組教學反思計劃
- 高值耗材采購制度及流程在醫(yī)院應用他
- 2025年河北廊坊市直事業(yè)單位招聘工作人員256人筆試歷年典型考題及考點剖析附帶答案詳解
- 2025年醫(yī)學綜合素質(zhì)考試題及答案
- 電大市場營銷試題及答案
- 北師大版(2024)七年級上冊生物期末復習全冊考點背誦提綱
- 《半年護理工作回顧與改進》課件
- 2025秋三年級上冊語文上課課件 3 不懂就要問
- 2025年湖南中考生物試題及答案
- Unit 2 Home Sweet Home 第1課時(Section A 1a-1d) 2025-2026學年人教版英語八年級下冊
- 送達地址確認書(法院最新版)
- 青島一?;瘜W試題
- 常德市自來水公司水表管理制度
評論
0/150
提交評論