Back-end/Java

Java - Chatting Project

HOONY_612 2021. 5. 30. 20:49
반응형

이번 주제는 미니 채팅 프로그램 만들기.

 

클라이언트와 서버가 서로 소통하게 하는 것이 최종 목표이다. 클라이언트에서 Data를 보내고 요구에 맞는 Data를 Database에서 빼서 다시 클라이언트로 넘겨주는 것의 일부분이다.

 

생각보다 간단하겠구나 생각했는데 예상보다 시간이 쫌 걸렸다.

 

일단 시작 전 소켓(Socket)과 스트림(Stream)이란 개념에 대해서 공부해보자.

 

1. Socket

 

네트워크상에서 동작하는 프로그램 간 통신의 종착점(Endpoint)입니다.

즉, 프로그램이 네트워크에서 데이터를 통신할 수 있도록 연결해주는 연결부이다.

 

위의 그림처럼 각각의 IP와 Port번호를 통해서 통신한다.

나는 서버와 클라이언트가 둘 다 똑같은 Local이기 때문에 IP는 같다. 그러나 Port번호는 다르다.

 

우리는 클라이언트와 서버가 통신하기 위해 소켓이라는 객체를 사용한다.

2가지를 사용하는데 ServerSocket, Socket이다.

ServerSocket서버용 소켓으로 포트를 통해 연결 요청을 받는 역할을 한다.

그리고 ServerSocket이 Accept되면 새로운 Socket객체를 만들어 클라이언트와 데이터를 주고 받는다.

Socket서버 프로그램으로 연결 요청을 하는 역할을 한다. 즉 데이터 전송을 주로 담당한다.

 

 

2. Stream

 

우린 흔히 "스트리밍서비스"라고 주위에서 많이 듣는다. 스트림은 입출력이 표현되는 데이터의 흐름이라고 생각하자.

아래의 그림을 참조하면 훨씬 이해가 쉽다. 즉 입.출력의 길을 만들어서 데이터를 통신하는 것이라고 생각하자.

 

 

스트림은 기본적으로 Byte단위로 데이터를 입.출력한다. 그래서 InputStreamOutputStream으로 나뉜다.

그리고 입력 스트림 일 경우 read(), 출력 스트림 일 경우 write()한다.

 

 

그리고 다양한 것들에 대한 입.출력 스트림을 정할 수 있다.

 

 

그리고 보조 스트림이 존재한다. 이것은 주 스트림(InputStream과 OutputStream)을 보조해주는 역할이다.

예를 들면 Java에서는 char형이 2Byte로 인식된다. 그러나 Java는 기본적으로 1Byte의 데이터를 처리한다.

이런 경우에 보조 스트림을 이용하여 데이터를 전송한다. 그리고 Buffer는 CPU를 훨씬 효율적으로 이용가능하게 한다.

 

 

 

이렇게 기본적인 Socket과 Stream의 설명이 끝나고 본 프로젝트 설명을 하겠다.

아래의 그림은 우리가 만들 프로젝트의 흐름도이다.

 

 

동작 과정을 설명하겠다.

 

1. ServerSocket 만들기

 

ServerSocket serverSocket = new ServerSocket();

 

2. ServerSocket IP Address Binding하기

 

String localHostAddress = InetAddress.getLocalHost().getHostAddress(); // IP저장.
serverSocket.bind(new InetSocketAddress(localHostAddress, SERVER_PORT)); // IP와 Port Binding.
System.out.println("[server] binding! \naddress:" + localHostAddress + ", port:" + SERVER_PORT); // IP와 Port연결 성공.

 

3. Accept Client요청 대기

 

 Socket socket = serverSocket.accept(); //Client요청 대기.(Blocking상태)

 

4. Client 연결 요청(따로 클라이언트를 동시에 실행시켜줘야함. Eclipse Consol 2 활용)

 

여기서 주의! 클라이언트 부분의 Port 따로 만들어짐 (ex>53467)

socket = new Socket(); //클라이언트 Socket생성.
socket.connect(new InetSocketAddress(SERVER_IP, SERVER_PORT)); // 서버 IP와 서버 PORT에 연결 시도. 

 

5. 연결 요청오면 연결 완료.

 

InetSocketAddress remoteSocketAddress =(InetSocketAddress)socket.getRemoteSocketAddress(); // 192.168.191.134:57841(IP와 Port)가 넘어옴
String remoteHostName = remoteSocketAddress.getAddress().getHostAddress(); // String으로 받기위해 getHostAddress()메소드 적용.(IP)
int remoteHostPort = remoteSocketAddress.getPort(); // Port받기.
System.out.println("[server] connected! \nconnected socket address:" + remoteHostName + ", port:" + remoteHostPort); //출력.

 

6. Server측과 Client Stream생성.

 

is = socket.getInputStream(); //instream 생성.
isr = new InputStreamReader(is, "UTF-8"); // byte단위로 들어오는 것을 char(2byte)형태로 인터페이스 제공.(보조 스트림)
br = new BufferedReader(isr); //한 글자씩 보내는 것보다 CPU의 효율을 위해 보조 스트림사용. "\n"을 기준으로 보냄(보조 스트림)

os = socket.getOutputStream(); //outstream 생성.
osw = new OutputStreamWriter(os, "UTF-8"); // byte단위로 나가는 것을 char(2byte)형태로 인터페이스 제공.(보조 스트림)
pw = new PrintWriter(osw, true); //출력가능하게 해주는 것.(보조 스트림)

 

7. 클라이언트와 서버간의 데이터 전달

 

pw.println(data); //서버나 클라이언트에서 상대 쪽으로 데이터를 보낼 때 사용.

data = br.readLine(); //서버나 클라이언트에서 상대 쪽에서 보낸 데이터를 읽을 떄 사용.(Blocking상태)

 

 

**클라이언트와 서버를 Eclipse에서 동시에 구동하기

 

여기서 시간을 많이 걸렸다.. 처음에 어떻게 할지 몰라서 계속 오류가 났다. 물론 cmd로도 할 수 있는데 java를 설치하고

cmd도 말을 안들어서 힘겨웠다. 그래서 Eclipse에서 클라이언트랑 서버를 구동하는 방법을 설명하겠다.

 

콘솔 창을 2개 띄우고 동그라미 부분을 클릭하면 저 콘솔창이 서버창이 된다.

그리고 Server를 실행시키고 서버는 Accept를 기다리는 상태일 것이다.

다음으로 Client를 실행시키면 아래와 같은 콘솔창이 열릴 것이다.

그리고 화살표(>>)부분에 말하고 싶은 것을 입력하면 완성!!

 

**결과물

 

 

반응형