자바 NIO 채 팅 방 의 예제 코드 구현(단체 채 팅+개인 채 팅)
기능:단체 채 팅+비공개+온라인 알림+오프라인 알림+온라인 사용자 조회
문건
Utils
Maven 으로 다음 가방 두 개 가 져 와 야 합 니 다.
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
package moremorechat_nio;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
/**
* @author mazouri
* @create 2021-05-09 22:26
*/
@Slf4j
public class Utils {
/**
*
*
* @param buf
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public static Message decode(byte[] buf) throws IOException, ClassNotFoundException {
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
ObjectInputStream ois = new ObjectInputStream(bais);
return (Message) ois.readObject();
}
/**
*
*
* @param message
* @return
*/
public static byte[] encode(Message message) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(message);
oos.flush();
return baos.toByteArray();
}
}
FinalValue
package moremorechat_nio;
/**
* @author mazouri
* @create 2021-05-05 21:00
*/
public final class FinalValue {
/**
*
*/
public static final int MSG_SYSTEM = 0;
/**
*
*/
public static final int MSG_GROUP = 1;
/**
*
*/
public static final int MSG_PRIVATE = 2;
/**
*
*/
public static final int MSG_ONLINE = 3;
/**
*
*/
public static final int MSG_NAME = 4;
}
Message
package moremorechat_nio;
import java.io.Serializable;
/**
* @author mazouri
* @create 2021-05-05 21:00
*/
public class Message implements Serializable {
public int type;
public String message;
public Message() {
}
public Message(String message) {
this.message = message;
}
public Message(int type, String message) {
this.type = type;
this.message = message;
}
@Override
public String toString() {
return "Message{" +
"type=" + type +
", message='" + message + '\'' +
'}';
}
}
NioServer
package moremorechat_nio;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import static moremorechat_nio.FinalValue.*;
/**
* ctrl+f12
* ctrl+alt+
* @author mazouri
* @create 2021-05-09 19:24
*/
@Slf4j
public class NioServer {
private Selector selector;
private ServerSocketChannel ssc;
public NioServer() {
try {
// selector, channel
selector = Selector.open();
// ServerSocketChannel, ,
ssc = ServerSocketChannel.open();
ssc.bind(new InetSocketAddress(8888));
//
ssc.configureBlocking(false);
// 2. selector channel ( )
// SelectionKey , channel
// ServerSocketChannel Reactor Selector , ACCEPT
ssc.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
NioServer server = new NioServer();
log.debug("server , ...");
try {
server.listen();
} catch (Exception e) {
log.debug(" ");
}
}
/**
*
*
* @throws Exception
*/
private void listen() throws Exception {
while (true) {
// select , , , , , Selector select() ( )
// Selector select() ( )
// select , , , ,
selector.select();
// , selectedKeys
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
// key , selectedKeys ,
iterator.remove();
//
if (key.isAcceptable()) {
ServerSocketChannel channel = (ServerSocketChannel) key.channel();
SocketChannel sc = channel.accept();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
dealReadEvent(key);
}
}
}
}
/**
*
*
* @param key
*/
private void dealReadEvent(SelectionKey key) {
SocketChannel channel = null;
try {
channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
int read = channel.read(buffer);
// ,read -1
if (read == -1) {
//cancel selector channel, keys key
key.cancel();
} else {
buffer.flip();
Message msg = Utils.decode(buffer.array());
log.debug(msg.toString());
dealMessage(msg, key, channel);
}
} catch (IOException | ClassNotFoundException e) {
System.out.println((key.attachment() == null ? " " : key.attachment()) + " ..");
dealMessage(new Message(MSG_SYSTEM, key.attachment() + " .."), key, channel);
//
key.cancel();
//
try {
channel.close();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}
/**
* ,
*
* @param msg
* @param key
* @param channel
*/
private void dealMessage(Message msg, SelectionKey key, SocketChannel channel) {
switch (msg.type) {
case MSG_NAME:
key.attach(msg.message);
log.debug(" {} ", msg.message);
getConnectedChannel(channel).forEach(selectionKey -> {
SocketChannel sc = (SocketChannel) selectionKey.channel();
sendMsgToClient(new Message(" : " + msg.message + " "), sc);
});
break;
case MSG_GROUP:
getConnectedChannel(channel).forEach(selectionKey -> {
SocketChannel sc = (SocketChannel) selectionKey.channel();
sendMsgToClient(new Message(key.attachment() + " : " + msg.message), sc);
});
break;
case MSG_PRIVATE:
String[] s = msg.message.split("_");
AtomicBoolean flag = new AtomicBoolean(false);
getConnectedChannel(channel).stream().filter(sk -> s[0].equals(sk.attachment())).forEach(selectionKey -> {
SocketChannel sc = (SocketChannel) selectionKey.channel();
sendMsgToClient(new Message(key.attachment() + " : " + s[1]), sc);
flag.set(true);
});
if (!flag.get()){
sendMsgToClient(new Message(s[1]+" , !!!"), channel);
}
break;
case MSG_ONLINE:
ArrayList<String> onlineList = new ArrayList<>();
onlineList.add((String) key.attachment());
getConnectedChannel(channel).forEach(selectionKey -> onlineList.add((String) selectionKey.attachment()));
sendMsgToClient(new Message(onlineList.toString()), channel);
break;
case MSG_SYSTEM:
getConnectedChannel(channel).forEach(selectionKey -> {
SocketChannel sc = (SocketChannel) selectionKey.channel();
sendMsgToClient(new Message(" : " + msg.message), sc);
});
break;
default:
break;
}
}
/**
*
*
* @param msg
* @param sc
*/
private void sendMsgToClient(Message msg, SocketChannel sc) {
try {
byte[] bytes = Utils.encode(msg);
sc.write(ByteBuffer.wrap(bytes));
} catch (IOException e) {
log.debug("sendMsgToClient ");
}
}
/**
* channel,
*
* @param channel
* @return
*/
private Set<SelectionKey> getConnectedChannel(SocketChannel channel) {
return selector.keys().stream()
.filter(item -> item.channel() instanceof SocketChannel && item.channel().isOpen() && item.channel() != channel)
.collect(Collectors.toSet());
}
}
NioClient
package moremorechat_nio;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
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.util.Iterator;
import java.util.Scanner;
import static moremorechat_nio.FinalValue.*;
/**
* @author mazouri
* @create 2021-04-29 12:02
*/
@Slf4j
public class NioClient {
private Selector selector;
private SocketChannel socketChannel;
private String username;
private static Scanner input;
public NioClient() throws IOException {
selector = Selector.open();
socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8888));
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
log.debug("client ......");
log.debug(" ");
input = new Scanner(System.in);
username = input.next();
log.debug(" {} ", username);
}
public static void main(String[] args) throws IOException {
System.out.println("tips:
1.
2. @ :
3. ");
NioClient client = new NioClient();
//
new Thread(() -> {
try {
client.acceptMessageFromServer();
} catch (Exception e) {
e.printStackTrace();
}
}, "receiveClientThread").start();
// sendMessageToServer,
client.sendMessageToServer();
}
/**
*
*
* @throws IOException
*/
private void sendMessageToServer() throws IOException {
//
Message message = new Message(MSG_NAME, username);
byte[] bytes = Utils.encode(message);
socketChannel.write(ByteBuffer.wrap(bytes));
while (input.hasNextLine()) {
String msgStr = input.next();
Message msg;
boolean isPrivate = msgStr.startsWith("@");
if (isPrivate) {
int idx = msgStr.indexOf(":");
String targetName = msgStr.substring(1, idx);
msgStr = msgStr.substring(idx + 1);
msg = new Message(MSG_PRIVATE, targetName + "_" + msgStr);
} else if (" ".equals(msgStr)) {
msg = new Message(MSG_ONLINE, " ");
} else {
msg = new Message(MSG_GROUP, msgStr);
}
byte[] bytes1 = Utils.encode(msg);
socketChannel.write(ByteBuffer.wrap(bytes1));
}
}
/**
*
*/
private void acceptMessageFromServer() throws Exception {
while (selector.select() > 0) {
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
if (key.isReadable()) {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
sc.read(buffer);
Message message = Utils.decode(buffer.array());
log.debug(String.valueOf(message.message));
}
}
}
}
}
자바 가 NIO 채 팅 방 을 실현 하 는 예제 코드(단체 채 팅+개인 채 팅)에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 NIO 채 팅 방 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.