inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

김영한의 실전 자바 - 고급 2편, I/O, 네트워크, 리플렉션

채팅 클라이언트 문의

116

헬로월드

작성한 질문수 2

0

안녕하세요. 채팅 클라이언트 실습전에 먼저 구현을 해보았는데요.

클라이언트 메인에서 스레드를 스타트 하면 그 즉시 소켓이 닫히면서 프로그램이 종료되는 오류를 겪었습니다.

이는 클라이언트 메인에서 sender 스레드를 join하면서 해결하긴 했는데요.

영한님의 예제에서는 start() 만 하여도 프로그램이 종료되지 않는데, 왜 저의 코드는 종료될까.... try with resources 가 문제인가 싶다가도 그건 아닐거 같은 모호한 상황에 놓여서....

제가 볼 땐 도무지 보이지 않아서, 코드 리뷰와 원인 파악을 부탁드리려고 질문을 남깁니다.

 

MessageHandler.java

package com.hoonjin.study.java.ionetwork.network.chat.client;

import lombok.RequiredArgsConstructor;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

import static com.hoonjin.study.java.util.MyLogger.log;

@RequiredArgsConstructor
public class MessageHandler implements Runnable {

    private final Socket socket;

    @Override
    public void run() {
        try (DataInputStream dis = new DataInputStream(socket.getInputStream())) {
            while (true) {
                String msg = dis.readUTF();
                log(msg);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

MessageSender.java

package com.hoonjin.study.java.ionetwork.network.chat.client;

import com.hoonjin.study.java.ionetwork.network.chat.Command;
import lombok.RequiredArgsConstructor;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Arrays;
import java.util.Scanner;

import static com.hoonjin.study.java.util.MyLogger.log;

@RequiredArgsConstructor
public class MessageSender implements Runnable {

    private static final String DELIMITER = "\\|";

    private final Socket socket;

    private boolean joined = false;

    @Override
    public void run() {
        Scanner scanner = new Scanner(System.in);
        try (DataOutputStream dos = new DataOutputStream(socket.getOutputStream())) {
            while (true) {
                log("input message with cmd: ");
                String msg = scanner.nextLine();
                if (msg.isEmpty()) {
                    continue;
                }
                String[] split = msg.split(DELIMITER);
                String cmd = split[0];

                if (Arrays.stream(Command.values()).noneMatch(c -> c.value().equals(cmd))) {
                    log("wrong command");
                    continue;
                }

                if (cmd.equals(Command.EXIT.value())) {
                    dos.writeUTF(msg);
                    joined = false;
                    break;
                } else if (cmd.equals(Command.JOIN.value())) {
                    joined = true;
                }

                if (joined) {
                    dos.writeUTF(msg);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

ChatClient.java

package com.hoonjin.study.java.ionetwork.network.chat.client;

import java.io.IOException;
import java.net.Socket;

public class ChatClient {

    private static final String SERVER = "localhost";
    private static final int PORT = 23456;

    public static void main(String[] args) throws IOException, InterruptedException {
        try (Socket socket = new Socket(SERVER, PORT)) {
            Thread messageHandler = new Thread(new MessageHandler(socket));
            Thread messageSender = new Thread(new MessageSender(socket));

            messageHandler.start();
            messageSender.start();

            messageSender.join(); // 이 부분이 없으면 시작하자마자 즉시 종료됨

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

Command.java

package com.hoonjin.study.java.ionetwork.network.chat;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public enum Command {
    JOIN("/join"),
    MESSAGE("/message"),
    CHANGE("/change"),
    USERS("/users"),
    EXIT("/exit")
    ;

    private final String value;

    public String value() {
        return value;
    }
}

 

이상입니다.

확인해주시면 감사하겠습니다.

새해복 많이 받으세요!

 

 

java 네트워크 객체지향

답변 1

0

David

안녕하세요. 헬로월드님, 공식 서포터즈 David입니다.

구현하는 부분의 강의를 들으신 후, 코드를 한 번 더 살펴보시고 그리고 나서 이해되지 않는 부분을 조금 더 자세히 알려주시면 좋을 것 같습니다:)

감사합니다.

RequestHandler 버전 간 process() 파라미터 차이 질문

0

76

2

리플렉션 default

0

57

1

그럼 SOURCE나 CLASS는 어떤 경우에 사용하나요?

0

83

2

네트워크 프로그램 자원종료 Socket 정리 시 closed 사용 문의

0

105

2

FileInputStream의 transferTo 사용 시 Buffer 문의

0

67

1

오타 제보 드립니다

0

76

2

강좌 복습 팁이 있으신 분들 공유해주시면 감사하겠습니다.

0

114

1

16강 질문있습니다.

0

53

1

한글이 깨질 떄 어떻게 해야 하나요?

0

83

1

자원 정리시 에러가 발생 했을 때 메모리 상황 및 실무에서 로그 확인 방법

0

96

1

인텔리제이에서 네모(스탑버튼) 누르는 것의 의미

-1

71

1

강의 섹션 8: 네드워크 -프로그램 3부분 10:45 오타?

0

90

2

제대로 이해한게 맞나 궁금합니다

0

80

1

File,Files 강의 2번쨰 Files 07:30 에 tmep 파일들을 다 지운건가요 ?

0

65

1

/.well-known/appspecific/com.chrome.devtools.json 에러에 대해서

0

639

1

Socket 자원을 정리할때 stream 을 정리하지 않는 이유가 궁금합니다.

0

95

1

클라이언트 강제종료시 오류 메세지

0

112

2

고급 2편에는 퀴즈가 없네요?

0

102

1

55. 네트워크 프로그램5 - 자원정리2 질문

0

69

1

클라이언트가 FIN과 함께 보내는 ACK는 무엇에 대한건가요?

1

111

2

BufferedInputStream이 1바이트씩 조회해도 성능이 좋은 이유

0

83

1

오타제보

0

65

2

문자 집합 호환성 여부를 판단할 때

0

55

1

utf-8, char

0

57

1