묻고 답해요
150만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
순위 정보를
불러오고 있어요
-
해결됨김영한의 실전 자바 - 고급 2편, I/O, 네트워크, 리플렉션
채팅 프로그램 구현완료 이후, 보완해야할거
[질문 내용]안녕하세요, 영한님 강의 잘 이용하고있습니다. 감사합니다.다름이아니라, 이번에 채팅프로그램을 구현하고나서 구현한 기능들에 대해서 보완할게 있는지 여쭤보고싶어서 글 남깁니다. 전체코드는 아래와 같습니다. ==================우선 구현한기능들은 잘 작동합니다./ 유저리스트 / 가입 / 메세지전송 / 메세지리드 / 제가 느끼기에는, 서버파일쪽에서 가독성이 크게 떨어지는거같은데 -> 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; } }
-
해결됨김영한의 실전 자바 - 고급 2편, I/O, 네트워크, 리플렉션
채팅프로그램 사용자 입력 받기 do-while 사용
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문 전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? 예2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? 예3. 질문 잘하기 메뉴얼을 읽어보셨나요? 예[질문 내용] 단순히 한번 입력 받는 게 아닌 do-while문을 사용하신 이유가 궁금합니다!
-
해결됨이해하면 인생이 바뀌는 네트워크 프로그래밍
ntohs() 와 htons() 함수의 차이
void packet_handler(u_char* param, const struct pcap_pkthdr* header, const u_char* pkt_data) // pcap_loop()가 돌면서 패킷을 감지할때 그 때 읽어들인 감청 데이터는 pkt_data 에 들어간다. { EtherHeader* pEther = (EtherHeader*)pkt_data; // 감청 데이터를 EtherHeader 로 형변환 printf( "SRC: %02X-%02X-%02X-%02X-%02X-%02X -> " "DST: %02X-%02X-%02X-%02X-%02X-%02X, type:%04X\n", pEther->srcMac[0], pEther->srcMac[1], pEther->srcMac[2], pEther->srcMac[3], pEther->srcMac[4], pEther->srcMac[5], pEther->dstMac[0], pEther->dstMac[1], pEther->dstMac[2], pEther->dstMac[3], pEther->dstMac[4], pEther->dstMac[5], //ntohs(pEther->type) pEther->type ); } ntohs(pEther->type) 과 htons(pEther->type)이 기능은 똑같다고 하는데, ntohs() 는 네트워크 오더 -> 호스트 오더 이고, htons() 는 호스트 오더->네트워크 오더 아닌가요?제가 Intel 프로세스 탑재한 PC에서 예제 실행중인데, 위 코드와 같이 실행하면 Ipv4 인 type 값이 0008로 나옵니다. 그래서 htons() 로 감싸서 출력하면 0800 으로 잘되는데 ntohs() 로 감쌌을떄는 왜 0800 이 나오는지 모르겠습니다.ntohs() 면 호스트 오더를 사용하는데 제 pc에서는 그대로 호스트 오더 방식으로 되야 하는거 아닌가요?
-
해결됨이득우의 언리얼 프로그래밍 Part3 - 네트웍 멀티플레이 프레임웍의 이해
섹션 1 - 4강 보고 제 방식대로 정리했는데 검토 부탁드립니다.
액터의 역할에 대해 그림으로 정리해봤는데요.제가 정확히 이해한게 맞을까요?
-
미해결CloudNet@와 함께하는 Amazon EKS 기본 강의
강의 연장 요청 드립니다.
안녕하세요, 1년이라는 수강기간이면 충분하다 생각했는데 곧 수강기간이 끝나게 되는데 아직 반밖에 진도를 못나갔네요..게으른 제 자신을 반성하며.... ㅠㅠ가능하다먼 수강기간 연장을 요청 드리고 싶습니다. 감사합니다-!
-
해결됨AWS Certified Solutions Architect - Associate 자격증 준비하기
수강 기간 연장 문의
안녕하세요, 좋은 강의 감사드립니다.업무와 병행하다 보니 공부할 시간 내기가 생각보다 어렵네요..수강 기간 연장을 부탁드려도 될까요?
-
해결됨CloudNet@와 함께하는 AWS 네트워킹 입문
강의 수장 연장 관련 문의
안녕하세요.현생이 바빠서 잊고 지냈는데, 남은 기한내에 남은 강의를 볼 수 없을 것 같아서 연장 문의 드립니다.저도 3개월 연장이 가능할까요?
-
미해결실습으로 배우는 핵심 네트워크 기술
ccnp
ccnp 대상의 중급이상 강의는 언제 나올까요?
-
미해결김영한의 실전 자바 - 고급 2편, I/O, 네트워크, 리플렉션
채팅 프로그램 관련 질문이 있습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문 전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용] 안녕하세요 영한님 코드는 제가 이해한 바로는세션 객체를 돌리는 스레드가 채팅을 다른 사람에게 전파하는 코드도 돌리는 걸로 알고 있습니다. 저는 채팅을 다른 사람에게 보내는 것을 맡은 객체를 따로 만들고 스레드도 따로 돌리게 만들었습니다. 혹시 이렇게 하는 게 좋은 건지 궁금합니다.이걸 가능하게 하기 위해서 ConcurrentLinkedQueue를 사용했고 각 세션이 채팅을 받으면 이 queue에 채팅 내용을 넣으면 이 queue를 담당하는 스레드에서 큐를 비워가면서 채팅을 각 사용자에게 보내게 했습니다. 근데 큐가 차 있는지 확인하는 방법을 잘 몰라서 0.1초마다 while문을 돌려서 큐가 차 있는지 확인하고 차 있으면 채팅을 보내게 했습니다. 이 방식이 굉장히 마음에 안 드는데 더 좋은 방법이 뭐가 있을지 궁금합니다.
-
미해결AWS Certified Solutions Architect - Associate 자격증 준비하기
실전문제풀이 pdf
안녕하세요.강의 잘 듣고 있습니다.실전문제풀이 부분 수강중인데 첨부된 강의자료에는 포함되지 않은 것 같습니다.자료를 어디서 찾을 수 있을까요?
-
미해결컴퓨터구조, 네트워크 기본 개념 정리
강의 자료
좋은 강의 무료로 학습할 기회를 주셔서 감사합니다.혹시 강의에서 사용하신, 강의 자료 공유 가능하실까요?도움이 많이 될 것 같아 여쭤봅니다.감사합니다.
-
미해결AWS Certified Solutions Architect - Associate 자격증 준비하기
수강 기간 연장 문의
안녕하세요 강사님 먼저 이렇게 좋은 강의 만들어주셔서 감사드립니다.부트캠프 활동과 같이 병행하려다보니 기간 안에 못 들을 거 같아서 연장 부탁 드리려고 문의 남깁니다. 감사합니다.
-
미해결자동차 SW - UDS 진단통신 정복하기
사용 프로그램
학습을 하다가 궁금한 사항이 하나 생겼습니다. 진단통신 관련 서비스들을 배우게 되면, 함수들을 CAPL에서 프로그래밍을 작성하여 진단을 하게 되는 건가요? 아님 다른 C언어나 리눅스를 이용해서 진단을 하나요? 엄청 초보적인 질문인데 궁금해서 여쭤봅니다.
-
미해결AWS Certified Solutions Architect - Associate 자격증 준비하기
수강 기간 연장 문의
안녕하세요. 시험날짜를 부득이하게 12/31 일정으로 잡아서 현재 수강기간에 연장을 부탁드려도 될까요..?
-
미해결김영한의 실전 자바 - 고급 2편, I/O, 네트워크, 리플렉션
EOFException에 대해 질문이 있습니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문 전에 다음을 꼭 확인해주세요.1. 강의 내용과 관련된 질문을 남겨주세요.2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.(자주 하는 질문 링크: https://bit.ly/3fX6ygx)3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예/아니오)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오)[질문 내용]EOFException이 일어나는 원리가 궁금합니다.그러니까 클라이언트에서 예상치 못한 연결 종료가 발생하면서버가 EOFException을 받는다는 건데 이게 어떤 원리로 발생하는 건가요?heartbeat를 사용해서 서버가 핑을 날렸는데 반응이 없어서 생겼다자바 프로그램이 강제 종료가 되면 os에서 클라이언트 소켓에 신호를 보낸다자바 프로그램이 강제 종료가 되어도 종료되기 전에 자바 프로그램이 클라이언트의 inputStream에 -1이라는 값을 보내고 종료한다 저는 이 중 하나라고 생각하는데 뭐가 맞는지 모르겠습니다.. 그리고 3번이 답이면 혹시 이런 과정을 거치기도 전에 종료해버리는 경우엔 어떻게 되는지 궁금합니다
-
해결됨AWS Certified Solutions Architect - Associate 자격증 준비하기
수강 기간 연장 부탁 드립니다!
나중에 들으려고 수강신청했었는데 기간제한이있었네요 ㅠㅠ아직 한번도 못봐서 기간 연장 부탁드립니다!
-
미해결AWS Certified Solutions Architect - Associate 자격증 준비하기
수강 기간 연장 부탁드립니다.
수강 연장 부탁드립니다..! 감사합니다.
-
미해결이득우의 언리얼 프로그래밍 Part3 - 네트웍 멀티플레이 프레임웍의 이해
액터 리플리케이션 빈도의 사용성에 관하여 질문드립니다.
분수대와 같이 동작이 예측되는 고정 액터의 경우에 클라이언트에서 로직을 실행하도록 해 네트워크 부하를 줄인다는 것을 이해했습니다. 그런데 분수대 액터와 같은 고정액터가 정말 많은 실제 게임 환경에서 실제로도 각각 액터 하나하나 컨트롤해주면서 최적화를 시켜주나요? 이런 최적화 과정 하나하나가 정말 중요한지, 아니면 리소스 낭비이지만 강의이기 때문에 컨트롤하고 넘어간 것인지 궁금합니다. 실제 현업에서 어떤식으로 활용하는지 그 기준이 있는지 궁금합니다. 감사합니다.
-
해결됨CloudNet@와 함께하는 Amazon EKS 기본 강의
강의 연장 요청드립니다.
곧 강의 수강 기간이 종료되어서요연장부탁드립니다.
-
미해결김영한의 실전 자바 - 고급 2편, I/O, 네트워크, 리플렉션
자바에서 2바이트 크기인 char에 할당되는 3바이트 크기의 한글...?
=========================================[질문 템플릿]1. 강의 내용과 관련된 질문인가요? (예)2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예)3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예)[질문 내용]안녕하세요. OutputStreamWriter, InputStreamReader를 이용해 한글을 파일에 쓰고 읽는 내용이 수업에 있는데요.UTF-8은 한글을 3바이트로 저장한다고 되어있고, 수업 때 작성한 코드를 보면 한글을 char 타입으로 저장이 잘 되는 것을 확인할 수 있습니다. (수업에서는 int형으로 저장했다가 이를 char형으로 캐스팅한것이지만 제가 따로 코딩을 해보아도 char 자료형에 한글이 잘 저장되더라구요) utf-8 에서는 한글을 3바이트로 저장하는데 자바에서 2바이트 크기인 char자료형에 잘 저장될 수 있는지 찾아보았는데, 자바에서는 변형된 utf-8을 쓴다고 하고 뭔가 굉장히 자세한 내용이 있었습니다.그냥 자바에서는 utf-8에서는 3바이트로 저장되는 한글을 특별한 방법으로 2바이트로 저장한다고 알고있으면 될까요?근데 또 한글로 저장해놓은 String을 바이트배열로 바꾸면 한글자당 세개의 바이트가 나와가지고 이해가 어렵습니다..
주간 인기글
순위 정보를
불러오고 있어요