- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > 編程語(yǔ)言 >
- 教你怎么用java實(shí)現客戶(hù)端與服務(wù)器一問(wèn)一答
開(kāi)啟多個(gè)客戶(hù)端
服務(wù)端效果:
客戶(hù)端效果:
當一個(gè)客戶(hù)端斷開(kāi)連接:
因為代碼中有注釋?zhuān)揖椭苯淤N上來(lái)了
服務(wù)端:
package com.dayrain.server; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.StandardCharsets; import java.util.Iterator; public class NioServer { /**端口**/ private static final int PORT = 8081; /**buffer大小**/ private static final int DEFAULT_BUFFER_SIZE = 1024; private final Selector selector; private final ByteBuffer readBuffer = ByteBuffer.allocate(NioServer.DEFAULT_BUFFER_SIZE); private final ByteBuffer writeBuffer = ByteBuffer.allocate(NioServer.DEFAULT_BUFFER_SIZE); private static int count = 0; public static void main(String[] args) throws IOException { new NioServer().start(); } public NioServer() throws IOException { //創(chuàng )建一個(gè)服務(wù)端channel ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //設置為非阻塞 serverSocketChannel.configureBlocking(false); //獲取服務(wù)器socket ServerSocket socket = serverSocketChannel.socket(); //綁定ip和端口 socket.bind(new InetSocketAddress(NioServer.PORT)); //創(chuàng )建多路復用選擇器,并保持打開(kāi)狀態(tài),直到close selector = Selector.open(); //將服務(wù)器管道注冊到selector上,并監聽(tīng)accept事件 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("server start on port: " + NioServer.PORT); start(); } public void start() throws IOException { //selector是阻塞的,直到至少有一個(gè)客戶(hù)端連接。 while (selector.select() > 0) { //SelectionKey是channel想Selector注冊的令牌,可以通過(guò)chancel取消(不是立刻取消,會(huì )放進(jìn)一個(gè)cancel list里面,下一次select時(shí)才會(huì )把它徹底刪除) Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); iterator.remove(); //當這個(gè)key的channel已經(jīng)準備好接收套接字連接 if(selectionKey.isAcceptable()) { connectHandle(selectionKey); } //當這個(gè)key的channel已經(jīng)準備好讀取數據時(shí) if(selectionKey.isReadable()) { readHandle(selectionKey); } } } } /** * 處理連接 * @param selectionKey */ private void connectHandle(SelectionKey selectionKey) throws IOException { //注意,服務(wù)端用的是ServerSocketChannel,BIO中是ServerSocket ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel(); SocketChannel socketChannel = serverSocketChannel.accept(); if(socketChannel == null) { return; } socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE); System.out.println("客戶(hù)端連接成功,當前總數:" + (++count)); writeBuffer.clear(); writeBuffer.put("連接成功".getBytes(StandardCharsets.UTF_8)); writeBuffer.flip(); socketChannel.write(writeBuffer); } /** * 讀取數據 * @param selectionKey */ private void readHandle(SelectionKey selectionKey){ SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); try { readBuffer.clear(); int read = socketChannel.read(readBuffer); if(read > 0) { readBuffer.flip(); String receiveData = StandardCharsets.UTF_8.decode(readBuffer).toString(); System.out.println("收到客戶(hù)端消息: " + receiveData); writeBuffer.clear(); writeBuffer.put(receiveData.getBytes(StandardCharsets.UTF_8)); writeBuffer.flip(); socketChannel.write(writeBuffer); } }catch (Exception e) { try { socketChannel.close(); } catch (IOException ioException) { ioException.printStackTrace(); } System.out.println("客戶(hù)端斷開(kāi)了連接~~"); count--; } } }
客戶(hù)端
package com.dayrain.client; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.StandardCharsets; import java.util.Iterator; public class NioClient { private static final int PORT = 8081; private static final int DEFAULT_BUFFER_SIZE = 1024; private final Selector selector; private final ByteBuffer readBuffer = ByteBuffer.allocate(NioClient.DEFAULT_BUFFER_SIZE); private final ByteBuffer writeBuffer = ByteBuffer.allocate(NioClient.DEFAULT_BUFFER_SIZE); public static void main(String[] args) throws IOException { NioClient nioClient = new NioClient(); //終端監聽(tīng)用戶(hù)輸入 new Thread(nioClient::terminal).start(); //這個(gè)方法是阻塞的,要放在最后 nioClient.start(); } public NioClient() throws IOException { selector = Selector.open(); SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(InetAddress.getLocalHost(), NioClient.PORT)); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); } public void start() throws IOException { while (selector.select() > 0) { Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); //拿到selectionKey后要刪除,否則會(huì )重復處理 iterator.remove(); if(selectionKey.isReadable()) { handleRead(selectionKey); } //只要連接成功,selectionKey.isWritable()一直為true if(selectionKey.isWritable()) { handleWrite(selectionKey); } } } } /** * 監聽(tīng)寫(xiě)操作 */ private void handleWrite(SelectionKey selectionKey) throws IOException { SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); // writeBuffer有數據就直接寫(xiě)入,因為另開(kāi)了線(xiàn)程監聽(tīng)用戶(hù)讀取,所以要上鎖 synchronized (writeBuffer) { writeBuffer.flip(); while (writeBuffer.hasRemaining()) { socketChannel.write(writeBuffer); } writeBuffer.compact(); } } /** * 監聽(tīng)讀操作 */ private void handleRead(SelectionKey selectionKey) throws IOException { SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); readBuffer.clear(); socketChannel.read(readBuffer); readBuffer.flip(); String res = StandardCharsets.UTF_8.decode(readBuffer).toString(); System.out.println("收到服務(wù)器發(fā)來(lái)的消息: " + res); readBuffer.clear(); } /** * 監聽(tīng)終端的輸入 */ private void terminal() { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); try { String msg; while ((msg = bufferedReader.readLine()) != null) { synchronized (writeBuffer) { writeBuffer.put((msg + "\r\n").getBytes(StandardCharsets.UTF_8)); } } }catch (Exception e) { e.printStackTrace(); } } }
到此這篇關(guān)于教你怎么用java實(shí)現客戶(hù)端與服務(wù)器一問(wèn)一答的文章就介紹到這了,更多相關(guān)java實(shí)現客戶(hù)端與服務(wù)器一問(wèn)一答內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站