java?NIO實現(xiàn)簡單聊天程序
本文實例為大家分享了java NIO實現(xià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();
}
}
//啟動服務(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);
}
}
}
客戶端
采用的時BIO,簡單的使用線程實現(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();
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
spring?Cloud微服務(wù)阿里開源TTL身份信息的線程間復(fù)用
這篇文章主要為大家介紹了spring?Cloud微服務(wù)中使用阿里開源TTL身份信息的線程間復(fù)用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-01-01
詳解lombok @Getter @Setter 使用注意事項
這篇文章主要介紹了詳解lombok @Getter @Setter 使用注意事項,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
Spring Boot實現(xiàn)Undertow服務(wù)器同時支持HTTP2、HTTPS的方法
這篇文章考慮如何讓Spring Boot應(yīng)用程序同時支持HTTP和HTTPS兩種協(xié)議。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-12-12
Spring-Security對HTTP相應(yīng)頭的安全支持方式
這篇文章主要介紹了Spring-Security對HTTP相應(yīng)頭的安全支持方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-10-10
Java并發(fā)編程中的ReentrantLock類詳解
這篇文章主要介紹了Java并發(fā)編程中的ReentrantLock類詳解,ReentrantLock是juc.locks包中的一個獨占式可重入鎖,相比synchronized,它可以創(chuàng)建多個條件等待隊列,還支持公平/非公平鎖、可中斷、超時、輪詢等特性,需要的朋友可以參考下2023-12-12
java設(shè)計模式-單例模式實現(xiàn)方法詳解
單例模式,屬于創(chuàng)建類型的一種常用的軟件設(shè)計模式。通過單例模式的方法創(chuàng)建的類在當前進程中只有一個實例(根據(jù)需要,也有可能一個線程中屬于單例2021-07-07

