java?NIO實(shí)現(xiàn)簡(jiǎn)單聊天程序
本文實(shí)例為大家分享了java NIO實(shí)現(xiàn)簡(jiǎn)單聊天程序的具體代碼,供大家參考,具體內(nèi)容如下
服務(wù)端
功能:
1、接受客戶端連接
2、發(fā)送消息
3、讀取客戶端消息
Server.java
public class Server { private Selector selector; private ByteBuffer writeBuffer = ByteBuffer.allocate(1024); private ByteBuffer readBuffer = ByteBuffer.allocate(1024); Msg msg = new Msg(); MsgSender msgSender = new MsgSender(msg); public static void main(String[] args) { Server server = new Server(); new Thread(server.msgSender).start(); server.start(); } //初始化服務(wù)端 public Server() { try { this.selector = Selector.open(); ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.configureBlocking(false); ssc.bind(new InetSocketAddress(8899)); ssc.register(this.selector, SelectionKey.OP_ACCEPT); System.out.println("服務(wù)端初始化完畢。。。。"); } catch (IOException e) { e.printStackTrace(); } } //啟動(dòng)服務(wù)端等待selector事件 public void start() { while (true) { try { int num = this.selector.select(); if (num > 0) { Iterator<SelectionKey> it = this.selector.selectedKeys().iterator(); while (it.hasNext()) { SelectionKey key = it.next(); it.remove(); if (key.isValid()) { if (key.isAcceptable()) { this.accept(key); } if (key.isReadable()) { this.read(key); } if (key.isWritable()) { this.write(key); } } } } } catch (IOException e) { e.printStackTrace(); } } } //發(fā)送消息 private void write(SelectionKey key) { SocketChannel sc = (SocketChannel) key.channel(); try { sc.configureBlocking(false); } catch (IOException e) { e.printStackTrace(); } //判斷是否有消息需要發(fā)送 if(msg!=null && msg.getFlag()){ System.out.println(msg); try { msg.setFlag(false); writeBuffer.clear(); writeBuffer.put(msg.getContent().getBytes()); writeBuffer.flip(); sc.write(writeBuffer); } catch (IOException e) { e.printStackTrace(); } } } //讀取客戶端消息 private void read(SelectionKey key) { SocketChannel sc = (SocketChannel) key.channel(); try { sc.configureBlocking(false); readBuffer.clear(); int read = sc.read(readBuffer); if (read == -1) { sc.close(); key.cancel(); } readBuffer.flip(); System.out.println(new String(readBuffer.array())); } catch (IOException e) { e.printStackTrace(); } } //接受客戶端連接 private void accept(SelectionKey key) { ServerSocketChannel ssc = (ServerSocketChannel) key.channel(); try { SocketChannel sc = ssc.accept(); System.out.println(String.format("a new client join!!!host:%s;port:%d", sc.socket().getLocalAddress(), sc.socket().getPort())); sc.configureBlocking(false); sc.register(this.selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE); } catch (IOException e) { e.printStackTrace(); } } }
Msg.java
class Msg { private Boolean flag=false; private String content; public Boolean getFlag() { return flag; } public void setFlag(Boolean flag) { this.flag = flag; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "Msg{" + "flag=" + flag + ", content='" + content + '\'' + '}'; } }
MsgSender.java
class MsgSender implements Runnable{ private Msg msg; public MsgSender(Msg msg) { this.msg = msg; } @Override public void run() { while (true) { System.out.println("input:\n"); Scanner scanner = new Scanner(System.in); this.msg.setContent(scanner.next()); this.msg.setFlag(true); } } }
客戶端
采用的時(shí)BIO,簡(jiǎn)單的使用線程實(shí)現(xiàn)消息的讀寫
功能:
1、連接服務(wù)端
2、讀取消息
3、發(fā)送消息
public class Client { private SocketChannel sc; ByteBuffer writeBuffer = ByteBuffer.allocate(1024); ByteBuffer readBuffer = ByteBuffer.allocate(1024); public static void main(String[] args) { new Client(); } public Client() { try { sc = SocketChannel.open(); //連接服務(wù)端 sc.connect(new InetSocketAddress(8899)); //發(fā)送消息 this.write(sc); //讀取消息 this.read(sc); } catch (IOException e) { e.printStackTrace(); } } private void read(SocketChannel sc) { new Thread(new Runnable() { @Override public void run() { while (true) { try { readBuffer.clear(); int read = sc.read(readBuffer); readBuffer.flip(); System.out.println(new String(readBuffer.array())); } catch (IOException e) { e.printStackTrace(); } } } }).start(); } private void write(SocketChannel sc) { new Thread(new Runnable() { @Override public void run() { while (true) { Scanner scanner = new Scanner(System.in); String next = scanner.next(); writeBuffer.clear(); writeBuffer.put(next.getBytes()); writeBuffer.flip(); try { sc.write(writeBuffer); } catch (IOException e) { e.printStackTrace(); } } } }).start(); } }
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
spring?Cloud微服務(wù)阿里開源TTL身份信息的線程間復(fù)用
這篇文章主要為大家介紹了spring?Cloud微服務(wù)中使用阿里開源TTL身份信息的線程間復(fù)用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01Spring?Cache抽象-使用SpEL表達(dá)式解析
這篇文章主要介紹了Spring?Cache抽象-使用SpEL表達(dá)式解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Java用自定義的類作為HashMap的key值實(shí)例
下面小編就為大家?guī)?lái)一篇Java用自定義的類作為HashMap的key值實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12詳解lombok @Getter @Setter 使用注意事項(xiàng)
這篇文章主要介紹了詳解lombok @Getter @Setter 使用注意事項(xiàng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Spring Boot實(shí)現(xiàn)Undertow服務(wù)器同時(shí)支持HTTP2、HTTPS的方法
這篇文章考慮如何讓Spring Boot應(yīng)用程序同時(shí)支持HTTP和HTTPS兩種協(xié)議。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12Spring-Security對(duì)HTTP相應(yīng)頭的安全支持方式
這篇文章主要介紹了Spring-Security對(duì)HTTP相應(yīng)頭的安全支持方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10Java并發(fā)編程中的ReentrantLock類詳解
這篇文章主要介紹了Java并發(fā)編程中的ReentrantLock類詳解,ReentrantLock是juc.locks包中的一個(gè)獨(dú)占式可重入鎖,相比synchronized,它可以創(chuàng)建多個(gè)條件等待隊(duì)列,還支持公平/非公平鎖、可中斷、超時(shí)、輪詢等特性,需要的朋友可以參考下2023-12-12java設(shè)計(jì)模式-單例模式實(shí)現(xiàn)方法詳解
單例模式,屬于創(chuàng)建類型的一種常用的軟件設(shè)計(jì)模式。通過(guò)單例模式的方法創(chuàng)建的類在當(dāng)前進(jìn)程中只有一個(gè)實(shí)例(根據(jù)需要,也有可能一個(gè)線程中屬于單例2021-07-07