해결된 질문
작성
·
218
·
수정됨
0
[질문 내용]
안녕하세요, 영한님 강의 잘 이용하고있습니다. 감사합니다.
다름이아니라, 이번에 채팅프로그램을 구현하고나서 구현한 기능들에 대해서 보완할게 있는지 여쭤보고싶어서 글 남깁니다. 전체코드는 아래와 같습니다.
==================
우선 구현한기능들은 잘 작동합니다.
/ 유저리스트 / 가입 / 메세지전송 / 메세지리드 /
제가 느끼기에는, 서버파일쪽에서 가독성이 크게 떨어지는거같은데
-> if / else / try / catch ... 때문에 ...
질문은 가독성 관련입니다.
가독성? --> if / else if 쪽을 어떻게 보완해야 가독성이 높아질 수 있을까요? ( 메서드 ? )
===================
[ close() 부분쪽은 따로 해결 완료했습니다! ]
서버파일입니다.
package chat;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import static util.MyLogger.log;
public class Server {
public static final int SERVER_PORT = 12345;
public static void main(String[] args) throws IOException {
log("서버를 시작합니다. 포트 번호 : " + SERVER_PORT);
ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
Thread acceptAndChat = new Thread(new AcceptThread(serverSocket));
acceptAndChat.start();
}
static class AcceptThread implements Runnable{
public ServerSocket serverSocket;
public AcceptThread(ServerSocket serverSocket) {
this.serverSocket = serverSocket;
}
@Override
public void run() {
Socket socket = null;
DataInputStream input = null;
DataOutputStream output = null;
while ( true ){
try {
socket = serverSocket.accept();
Sockets.addSocket(socket);
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
Thread chatThread = new Thread(new ChatThread(socket, input, output)); // 채팅관련 로직을 진행하는 스레드입니다.
chatThread.start();
}
catch (IOException e) {
log("서버 연결 도중에 문제가 발생했습니다 : " + e.getMessage() + " 프로그램을 종료합니다.");
try {
output.close();
input.close();
socket.close();
serverSocket.close();
} catch (IOException ee) {
log("자원정리도중 에러발생 : " + ee.getMessage());
}
}
}
}
}
static class ChatThread implements Runnable{
public Socket socket;
public DataInputStream input;
public DataOutputStream output;
public ChatThread(Socket socket, DataInputStream input, DataOutputStream output) {
this.socket = socket;
this.input = input;
this.output = output;
}
@Override
public void run() {
String currentThreadName;
List<String> threadsNames = new ArrayList<>();
boolean isFirst;
while ( true ) {
String received = "";
try {
received = input.readUTF();
} catch (IOException e) {
if ( e.equals("Connection reset") ){
log("사용자가 연결을 종료했습니다. 해당 사용자의 세션을 삭제합니다.");
Sockets.removeSocket(socket);
break;
}
log("클라이언트로부터 전송된 메세지를 받는도중, 에러가 발생했습니다 : " + e.getMessage());
break;
}
if ( received.equals("exit") ){
log("프로그램 종료 - 유저 요청");
break;
}
else if ( received.equals("list") ){
List<String> userNames = Users.getUserNames();
log("사용자가 목록 조회를 했습니다.");
try {
output.writeUTF(String.valueOf(userNames));
} catch (IOException e) {
log("사용자 목록을 유저에게 보내는도중, 에러가 발생했습니다");
}
}
else {
// 유저가 처음 채팅방에 입장했을때, 유저 닉네임을 참여자목록에 넣어주는 과정입니다.
currentThreadName = Thread.currentThread().getName();
isFirst = threadsNames.contains(currentThreadName);
if ( !isFirst ){
log("사용자 : " + received + " 님이 채팅방에 입장했습니다.");
Users.addUserName(received);
log("유저를 추가했습니다.");
threadsNames.add(currentThreadName);
System.out.println(threadsNames);
log("스레드를 추가했습니다.");
}
// 유저가 입장하고나서, 메세지를 전송하면 서버가 메세지를 받아서 메세지를 Sockets 에 있는 Socket 들에 전송하는 과정입니다.
else {
log("클라이언트로부터 메세지가 도착했습니다 : " + received);
// 메세지를 Sockets 에 있는 Socket 들에 전송
try {
Sockets.sendMessage(received);
} catch (IOException e) {
log("서버에서 클라이언트로 메세지를 전송하는 도중, 에러 발생 : " + e.getMessage());
}
}
log("테스트");
}
}
}
}
}
클라이언트 파일입니다.
package chat;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
import static chat.Server.SERVER_PORT;
import static util.MyLogger.log;
public class Client {
public static void main(String[] args) throws IOException, InterruptedException {
Socket socket = new Socket("localhost", SERVER_PORT); // 서버와 연결
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
Scanner scanner = new Scanner(System.in);
System.out.print("/join 을 입력해서 채팅방에 입장하세요 :");
String toJoin = scanner.nextLine();
if ( !toJoin.equals("/join") ){
System.out.println("명령어를 정확하게 입력해주세요. 재시작합니다.");
}
else {
System.out.print("채팅방에서 사용할 닉네임을 입력해주세요 : ");
String userName = scanner.nextLine(); // 닉네임입력 -> 채팅방 입장
// 닉네임 -> 서버에 전송 -> 서버가 유저모음집에 유저닉네임을 넣어줌
log(userName + " 채팅방에 입장했습니다.");
output.writeUTF(userName);
Thread sendThread = new Thread(() -> {
while ( true ){
System.out.print("전송할 메세지를 입력해주세요 ( 종료 : exit ) : ");
String toSend = scanner.nextLine();
if (toSend.equals("exit")) {
System.out.println("프로그램을 종료합니다.");
return;
}
try {
output.writeUTF(toSend); // 전송할 메세지를 서버에 전송
} catch (IOException e) {
log("메세지 전송도중 에러발생");
}
}
});
Thread receiveThread = new Thread(() -> {
while ( true ) {
String received = null;
try {
received = input.readUTF();
} catch (IOException e) {
log("메세지를 읽는도중 에러발생 : " + e.getMessage());
}
log("메세지가 도착했습니다 : " + received);
}
});
sendThread.start();
receiveThread.start();
sendThread.join();
receiveThread.join();
}
// 채팅 프로그램을 종료했으니, 자원을 정리하고 종료합니다.
log("채팅 프로그램 종료, 자원을 정리하고 종료합니다.");
input.close();
output.close();
socket.close();
}
}
======= 아래 두개는 서버 / 클라이언트 파일이아닌 도움을 주는 파일입니다.
서버와 클라이언트간에 소켓이 연결되고나서, 클라이언트 정보들이 담겨져있는 소켓들을 저장하는 공간입니다.
package chat;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class Sockets {
private static Map<Socket, Boolean> sockets = new HashMap<>();
public static void addSocket(Socket socket){
sockets.put(socket, true);
}
public static void sendMessage(String message) throws IOException {
for (Socket socket : sockets.keySet()) {
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
output.writeUTF(message);
}
}
public static void removeSocket(Socket socket){
sockets.remove(socket);
}
public static Boolean getValue(Socket socket) {
return sockets.get(socket);
}
public static boolean changeValue(Socket socket){
return sockets.get(socket);
}
}
채팅방에 접속한 유저들을 모아놓은 공간입니다.
package chat;
import java.util.ArrayList;
import java.util.List;
public class Users {
private static List<String> userNames = new ArrayList<>();
public static void addUserName(String userName){
userNames.add(userName);
}
public static List<String> getUserNames() {
return userNames;
}
}