간단한 채팅프로그램 만들기 3/3

살찐성인·2022년 7월 31일
0

Java

목록 보기
2/4

다시 Server 클래스로 돌아와서, 이제는 메세지를 입력받아 보낼 변수와 받는 변수를 선언하고 초기화한다. 그리고 입력을 받을 Scanner 클래스도 하나 임포트한 후 객체를 생성해준다. Client 클래스도 똑같이 세 줄을 작성한다.

String sendMsg = "";
String recvMsg = "";
Scanner sc = new Scanner(System.in);

그 다음에는 try/catch문이 끝나는 다음 부분에 작성을 시작하면 된다. 우선 가장먼저 서버 측에서 메세지를 보내야 한다. 스캐너로 입력받은 데이터를 클라이언트 측으로 보내야 하므로 dis(DataInputStream)와 dos(DataOutputStream) 중 dos를 사용한다.

System.out.print("서버(나) : ");
sendMsg = sc.nextLine();
dos.writeUTF(sendMsg);

dos.writeUTF(sendMsg)는 DataOutputStream 클래스의 writeUTF를 사용하여 스캐너를 통해 입력받은 sendMsg을 output한다는 의미이다. 이 writeUTF는 checked exception이므로 try/catch로 감싸주어야 한다. 감싼 후에 나머지 두 줄을 try문 안쪽으로 이동시킨다.

이제 Server에서 데이터를 보내는 코드를 만들었으니, 반대로 Client에서 데이터를 받는 코드를 작성해보자.
마찬가지로 try/catch가 끝나는 부분에 작성을 시작하면 된다. 아까 Server에서는 writeUTF를 사용했다면, 이번에는 readUTF를 사용하면 된다. 그리고 가이드 메세지로 다음과 같이 적게 되면, Server에서 보낸 데이터를 readUTF를 통해 recvMsg에 저장이 되는 것을 표현할 수 있다. dis.readUTF도 checked exception이므로 try/catch로 감싸도록 하자.

recvMsg = dis.readUTF();
System.out.println("서버(상대) : " + recvMsg);

하지만 이것만으로는, 현재 서버에서 보낸 채팅을 Client에서 한번 받아본 뒤 프로그램은 종료되고 만다. 따라서 Client 측에서도 메세지를 보내고, Server도 이를 읽어올 수 있도록 작성해보자.

Client 클래스에서 위에서 작성한 부분에 이어서 아래와 같이 적어보자. 이미 예외처리가 된 상태이므로 따로 try/catch를 쓸 필요는 없으며 아래 3줄을 잘 살펴보면 Server에서 보낸 것과 똑같은 것을 확인할 수 있다.

System.out.print("클라이언트(나) : ");
sendMsg = sc.nextLine();
dos.writeUTF(sendMsg);

그리고 이번에는 반대로 Server 클래스로 가서, Client에서 적었던 것과 똑같이 적어주면 된다.

recvMsg = dis.readUTF();
System.out.print("클라이언트(상대) : “ + recvMsg);

하지만 이것만으로는 채팅을 종료할 수도 없으며, 채팅이 서로 한번씩만 주고받을 수 있는 상태이다. 따라서 계속적으로 채팅을 이용하기 위해 while문을 활용하여 작성해보자.

Server클래스로 와서 try/catch로 감쌌던 부분을 while문으로 감싼다. 그리고 while문을 나가는 코드도 집어넣어야 채팅을 종료할 수 있으므로 아래와 같이 if문과 break를 이용하여 종료할 수 있도록 하며, 둘 중 아무나 채팅으로 exit를 입력하게 되면 채팅이 종료되도록 만들어 보았다.

while (true) {
	try {
		System.out.print("서버(나) : ");
		sendMsg = sc.nextLine();
		dos.writeUTF(sendMsg);
		if (sendMsg.equals("exit"))
			break; 
		recvMsg = dis.readUTF();
		if (recvMsg.equals("exit"))
			break;
		System.out.println("클라이언트(상대) : " + recvMsg);
      } catch (IOException e) {
		e.printStackTrace();
	}
}

Client도 Server와 같이 아래처럼 똑같이 작성해주면 된다.

while (true) {
	try {
		recvMsg = dis.readUTF();
		if (recvMsg.equals("exit"))
			break;
		System.out.println("서버(상대) : " + recvMsg);
		System.out.print("클라이언트(나) : ");
		sendMsg = sc.nextLine();
		dos.writeUTF(sendMsg);
		if (sendMsg.equals("exit"))
			break;
	} catch (IOException e) {
		e.printStackTrace();
	}
}

마지막으로 채팅이 끝난 경우에 채팅이 종료됐다는 메세지 출력이 필요하므로 while문이 끝나는 곳에 채팅프로그램을 종료한다는 가이드 메세지를 작성한다. 그리고 자원해제까지 해주면 좋다. 사용했던 InputStream이나 Socket 등을 닫아줌으로써 좀 더 원활한 프로그램을 만들 수 있게 된다. 작성은 아래처럼 쓰면 되며, 이것 또한 checked exception이므로 try/catch로 감싸주자. Server와 Client 모두 똑같이 적어주면 된다. 끝.

System.out.println("채팅을 종료합니다.");
	try {
		dos.close();
		dis.close();
		is.close();
		os.close();
		socket.close();
		sc.close();
	} catch (IOException e) {
		e.printStackTrace();
	}

Server 최종본

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class ChattingServer {
	public static void main(String[] args) {
		ServerSocket serverSocket = null;
		Socket socket = null;
		int port = 8999;
		InputStream is = null;
		OutputStream os = null;
		DataInputStream dis = null;
		DataOutputStream dos = null;

		String sendMsg = "";
		String recvMsg = "";
		Scanner sc = new Scanner(System.in);
		try {
			System.out.println("채팅서버를 구동중입니다...");
			Thread.sleep(2000);
			serverSocket = new ServerSocket(port);
			System.out.println("채팅서버를 구동하였습니다!");
			Thread.sleep(2000);
			System.out.println("클라이언트의 접속을 기다리고 있습니다.");
			socket = serverSocket.accept();
			System.out.println("클라이언트가 접속하였습니다.");
			is = socket.getInputStream();
			os = socket.getOutputStream();
			dis = new DataInputStream(is);
			dos = new DataOutputStream(os);
			System.out.println("채팅이 시작되었습니다.");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		while (true) {
			try {
				System.out.print("서버(나) : ");
				sendMsg = sc.nextLine();
				dos.writeUTF(sendMsg);
				if (sendMsg.equals("exit"))
					break; 
				recvMsg = dis.readUTF();
				if (recvMsg.equals("exit"))
					break;
				System.out.println("클라이언트(상대) : " + recvMsg);
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		System.out.println("채팅서버를 종료합니다.");
		try {
			dis.close();
			dos.close();
			os.close();
			is.close();
			serverSocket.close();
			socket.close();
			sc.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Client 최종본

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class ChattingClient {
	public static void main(String[] args) {
		Socket socket = null;
		String address = "127.0.0.1";
		int port = 8999;
		InputStream is = null;
		OutputStream os = null;
		DataInputStream dis = null;
		DataOutputStream dos = null;

		String sendMsg = "";
		String recvMsg = "";
		Scanner sc = new Scanner(System.in);
		try {
			System.out.println("서버에 연결중입니다..");
			socket = new Socket(address, port);
			System.out.println("채팅서버에 접속하였습니다.");
			is = socket.getInputStream();
			os = socket.getOutputStream();
			dis = new DataInputStream(is);
			dos = new DataOutputStream(os);
			System.out.println("서버와의 채팅을 시작합니다.");
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		while (true) {
			try {
				recvMsg = dis.readUTF();
				if (recvMsg.equals("exit"))
					break;
				System.out.println("서버(상대) : " + recvMsg);
				System.out.print("클라이언트(나) : ");
				sendMsg = sc.nextLine();
				dos.writeUTF(sendMsg);
				if (sendMsg.equals("exit"))
					break;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		System.out.println("채팅을 종료합니다.");
		try {
			dos.close();
			dis.close();
			is.close();
			os.close();
			socket.close();
			sc.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

0개의 댓글