[JAVA] 소켓(Socket) 으로 채팅/계산기/야구게임 프로그램 만들기 (Feat.보조스트림)

JoJo·2023년 7월 18일
0

💡 채팅 프로그램


✔️ 결과 화면

✔️ 서버 소켓(Server Socket) 소스코드

[Server]

package com.kh.day17.network.socket.chat;

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;      // ServerSocket 클래스 선언
		int port = 8888;				      // 포트 번호 변수선언
		InputStream is = null;			      // InputStream 선언 및 초기화
		OutputStream os = null;				  // OutputStream 선언 및 초기화
		DataInputStream dis = null;		     // 보조스트림, 기본 데이터타입, 입출력 도와줌
		DataOutputStream dos = null;		 // 보조스트림, 기본 데이터타입, 입출력 도와줌
		Scanner sc = new Scanner(System.in); // System.in -> 표준 입력 스트림
		
		try {
			//=========================== 서버 구동 ===========================
			System.out.println("채팅 서버를 구동중입니다..");
			serverSocket = new ServerSocket(port);
			System.out.println("채팅 서버를 구동하였습니다.");
			System.out.println("클라이언트의 접속을 기다리고 있습니다.");
			Socket socket = serverSocket.accept();	// accept() -> 소켓 객체를 리턴
			System.out.println("클라이언트가 접속하였습니다.");
			
			//=========================== 채팅 준비 ===========================
			is = socket.getInputStream();
			os = socket.getOutputStream();
			dis = new DataInputStream(is);	// 객체 생성(전달값은 주 스트림(is))
			dos = new DataOutputStream(os);	// 객체 생성(전달값은 주 스트림(os))
			System.out.println("채팅이 시작되었습니다.");
			
			// 무한 반복
			while(true) {
				//========================= 데이터 보내기 =========================
				System.out.print("서버(나) : ");
				String sendMsg = sc.nextLine();
				dos.writeUTF(sendMsg);// 보조스트림의 메소드 사용해서 데이터 바로 보내기
				dos.flush();			    // 버퍼 비우기
				
				//========================== 데이터 받기 ==========================
				// readUTF() -> server 에서 보낸 데이터를 바로 읽는다.
				// (UTF로 보냈기 때문에 UTF로 받음)
				String recMsg = dis.readUTF();	// 데이터 받기
				System.out.printf("클라이언트(상대) : %s\n", recMsg);
				
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

✔️ 클라이언트 소켓(Client Socket) 소스코드

[Client]

package com.kh.day17.network.socket.chat;

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) {
		// 서버에 연결중입니다.
		// 채팅서버에 접속하였습니다.
		// 서버와의 채팅을 시작합니다.
		// 서버(상대) : 하이
		// 클라이언트(나) : 네네
		
		String address = "127.0.0.1";	// server IP주소
		int port = 8888;				// server 포트 번호 변수
		InputStream is = null;			// InputStream 선언 및 초기화
		OutputStream os = null;			// OutputStream 선언 및 초기화
		DataInputStream dis = null;		// 보조스트림, 기본 데이터타입, 입출력 도와줌
		DataOutputStream dos = null;	// 보조스트림, 기본 데이터타입, 입출력 도와줌
		Scanner sc = new Scanner(System.in);	// System.in -> 표준 입력 스트림
		
		try {
			//=========================== 서버 연결 ===========================
			System.out.println("서버에 연결중입니다.");
			Socket socket = new Socket(address, port);	// Socket 객체 생성
			System.out.println("채팅서버에 접속하였습니다.");
			
			//=========================== 채팅 준비 ===========================
			is = socket.getInputStream();
			os = socket.getOutputStream();
			dis = new DataInputStream(is);	// 객체 생성(전달값은 주 스트림(is))
			dos = new DataOutputStream(os);	// 객체 생성(전달값은 주 스트림(os))
			System.out.println("서버와의 채팅을 시작합니다.");
			
			// 무한 반복
			while(true) {
				//========================== 데이터 받기 ==========================
				// readUTF() -> server 에서 보낸 데이터를 바로 읽는다.
				// (UTF로 보냈기 때문에 UTF로 받음)
				String recMsg = dis.readUTF();	// 데이터 받기
				System.out.printf("서버(상대) : %s\n", recMsg);
				
				//========================= 데이터 보내기 =========================
				System.out.print("클라이언트(나) : ");
				String sendMsg = sc.nextLine();
				dos.writeUTF(sendMsg);// 보조스트림의 메소드 사용해서 데이터 바로 보내기
				dos.flush();			    // 버퍼 비우기
				
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}



💡 계산기 프로그램


✔️ 결과 화면

✔️ 서버 소켓(Server Socket) 소스코드

package com.kh.day17.network.socket.calculator;

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 CalCulatorServer {

	public static void main(String[] args) {
		// 서버 구동중입니다.
		// 클라이언트 연결을 기다리고 있습니다...
		// 클라이언트와 연결되었습니다.
		// 받은 메세지 : 23
		// 받은 메세지 : 24 + 42
		// 클라이언트가 종료하였습니다.
		
		ServerSocket serverSocket = null;	// ServerSocket 초기화
		int port = 8888;					// 포트 번호 변수선언
		InputStream is = null;
		OutputStream os = null;
		DataInputStream dis = null;
		DataOutputStream dos = null;
		Scanner sc = new Scanner(System.in);
		// 한번에 import -> Ctrl + Shift + o
		
		
		try {
//			System.out.println(".");
//			Thread.sleep(1000);
//			System.out.println(".");
//			Thread.sleep(1000);
//			System.out.println(".");
//			Thread.sleep(1000);
			
			// ==================== 서버 구동 ====================
			System.out.println("서버 구동중입니다.");
			for(int i = 1; i <= 50; i++) {
				System.out.print("=");
				// 텍스트 지연 주기, 1000 -> 1초
				Thread.sleep(10); // 로딩 올라가는 효과 줄 수 있음
			}
			System.out.print("100%");
			System.err.println();
			serverSocket = new ServerSocket(port);
			System.out.println("클라이언트 연결을 기다리고 있습니다...");
			Socket socket = serverSocket.accept();
			System.out.println("클라이언트와 연결되었습니다.");
			
			// ================ 데이터 송수신 준비  ================
			is = socket.getInputStream();
			os = socket.getOutputStream();
			dis = new DataInputStream(is);
			dos = new DataOutputStream(os);
			
			// 무한 반복
			while(true) {
				// =================== 데이터 받기  ===================
				// 클라이언트에서 보낸 종료메세지 받기
				
				String recvMsg = dis.readUTF();
				// 클라이언트에서 종료메세지 보냈을 경우
				if(recvMsg.equalsIgnoreCase("exit")) {
					System.out.println("클라이언트가 종료하였습니다.");
					break;
				}
				System.out.printf("받은 메세지 : %s\n", recvMsg);
				// 24 + 42 -> 띄어쓰기 기준으로 문자열 배열을 만듬 
				// int num1, num2;
				// 공백 기준으로 문자열 나누기
				String [] msgArrs = recvMsg.split(" ");
				
				// 띄어쓰기 안해서 배열의 길이가 3이 아닐 경우
				// Client에 데이터 보내기
				if (msgArrs.length != 3) {
					String errMsg = "end";
					dos.writeUTF(errMsg);
					continue;	// 반복문이 다시 동작해야하기 때문에 continue 사용
				}
				// 24 / + / 42
				// 문자열 -> 정수, 데이터 타입 변환
				int num1 = Integer.parseInt(msgArrs[0]);
				int num2 = Integer.parseInt(msgArrs[2]);
				String operator = msgArrs[1];
				String result = "";	// writeUTF() 의 반환값이 String 이기 때문에.
				
				switch(operator) {
					case "+" : 
						result = String.valueOf(num1 + num2);	// 문자열로 변환
						
						break;
					case "-" : 
						result = String.valueOf(num1 - num2);
						break;
					case "*" : 
						result = num1 * num2 + ""; // 계산한 결과값에 문자열만나면 
																			 // 문자열로 변환 됨.
						break;
					case "/" : 
						result = num1 / num2 + "";
						break;
					case "%" : 
						result = num1 % num2 + "";
						break;
				}
				
				// =================== 데이터 보내기  ===================
				// The method writeUTF(String) in the type DataOutputStream is 
				// not applicable for the arguments (int)
				// => writeUTF() 의 반환값은 String 이어야 함.
				dos.writeUTF(result);
				dos.flush();	// 버퍼 비우기
				
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

✔️ 클라이언트 소켓(Client Socket) 소스코드

package com.kh.day17.network.socket.calculator;

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 CalCulatorClient {

	public static void main(String[] args) {
		// 서버와 연결되었습니다.
		// 계산식(빈칸으로 띄어 입력, 예 24 + 42) >> 23
		// 잘못 입력하셨습니다. 형식에 맞게 입력해주세요.
		// 계산식(빈칸으로 띄어 입력, 예 24 + 42) >> 24 + 42
		// 계산결과 : 66
		// 계산식(빈칸으로 띄어 입력, 예 24 + 42) >> exit
		
		String address = "127.0.0.1";
		int port = 8888;
		InputStream is = null;
		OutputStream os = null;
		DataInputStream dis = null;
		DataOutputStream dos = null;
		Scanner sc = new Scanner(System.in);
		
		try {
			// ==================== 서버 연결  ====================
			Socket socket = new Socket(address, port);
			System.out.println("서버와 연결되었습니다.");
			
			// ================ 데이터 송수신 준비  ================
			is = socket.getInputStream();
			os = socket.getOutputStream();
			dis = new DataInputStream(is);
			dos = new DataOutputStream(os);
			
			// ================== 데이터 보내기  ==================
			// 무한 반복
			for(;;) {
				System.out.print("계산식(빈칸으로 띄어 입력, 예 24 + 42) >> ");
				String sendMsg = sc.nextLine();
				
				// Null pointer access: The variable dos can 
				// only be null at this location
				// => dos 객체 생성 안했을 경우 뜨는 오류메세지
				dos.writeUTF(sendMsg);
				
				// 클라이언트에서 서버에 종료 메세지 보냈을 경우
				if(sendMsg.equalsIgnoreCase("exit")) {
					System.out.println("종료하였습니다.");
					break;
				}
				
				dos.flush();	// 버퍼 비우기
				
				// ================== 데이터 받기  ==================
				String recvMsg = dis.readUTF();
				
				// 잘못 입력했을 경우
				if(recvMsg.equalsIgnoreCase("end")) {
					System.out.println("잘못 입력하셨습니다. 형식에 맞게 입력해주세요.");
					continue;
				}
				
				System.out.printf("계산 결과 : %s\n", recvMsg);
				
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}



💡 야구 게임 프로그램


✔️ 결과 화면

✔️ 서버 소켓(Server Socket) 소스코드

[Server]

package com.kh.day17.network.socket.baseball;

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.Date;
import java.util.Scanner;

public class BaseballServer {

		public static void main(String[] args) {
//			서버소켓을 생성하였습니다.
//			2023-07-18 12:04:56:15
//			클라이언트의 접속을 기다립니다.
//			클라이언트가 접속했습니다.
//			서버 숫자 -> 7 3 8
//			서버 준비 완료
//			받기 : 4 2 1
//			0스트라이크 0볼
//			받기 : 1 2 3
//			0스트라이크 1볼
//			받기 : 2 3 4
//			1스트라이크 0볼
//			받기 : 5 3 8
//			2스트라이크 0볼
//			받기 : 5 3 7
//			1스트라이크 1볼
//			받기 : 7 3 8
//			3스트라이크 0볼
//			아웃! 게임종료
			
			int port = 8888;
			
			ServerSocket serverSocket = null;
			Date date = new Date();
			Scanner sc = new Scanner(System.in);
			InputStream is = null;
			OutputStream os = null;
			DataInputStream dis = null;
			DataOutputStream dos = null;
			int [] numbers = new int[3];	// 중복 제거를 위한 배열
			
			try {
				// =================== 서버 구동 ===================
				serverSocket = new ServerSocket(port);
				System.out.println("서버소켓을 생성하였습니다.");
				Thread.sleep(1500);
				System.out.println("클라이언트의 접속을 기다립니다.");
				Socket socket = serverSocket.accept();
				System.out.println("클라이언트가 접속했습니다.");
				System.out.print("서버 숫자 -> ");
				
				// 랜덤 숫자 부여
				// (int) Math.random() * (최댓값 - 최솟값 + 1) + 최소값
				for(int i = 0; i < 3; i++) {
					// 중복없이 난수 추출하기
					numbers[i] = (int)(Math.random()*9+1);
					for(int j = 0; j < i; j++) {
						// #1 skip
						// 		   j			 i
						// #2
						// numbers[0] == numbers[1]
						// #3
						// numbers[0] == numbers[2]
						// numbers[1] == numbers[2]
						// -> 중복 비교 순서
						if(numbers[j] == numbers[i]) {
							i--;
							break;	// 난수 구하는 for문 끝내기
						}
					}
				}
				System.out.printf("%d %d %d\n", numbers[0], numbers[1], numbers[2]);
				System.out.println("서버 준비 완료");
				
				// =============== 데이터 송수신 준비 ==============
				is = socket.getInputStream();
				os = socket.getOutputStream();
				dis = new DataInputStream(is);
				dos = new DataOutputStream(os);
				
				// 무한 반복
				while(true) {
					// ================== 데이터 받기 ==================
					String recvMsg = dis.readUTF();
					System.out.printf("받기 : %s\n", recvMsg);
					
					// ================= 데이터 보내기 =================
					// numbers배열과 입력한 값으로 만든 배열과 비교
					String [] inputNums = recvMsg.split(" ");
					int strike = 0;
					int ball = 0;
					for(int i = 0; i < 3; i++) {
						for(int j = 0; j < 3; j++) {
							// 값 비교
							if(numbers[i] == Integer.parseInt(inputNums[j])) {
								// 인덱스 비교
								if(i == j) {	// 값이 같은 상태에서 인덱스가 같으면 스트라이크
									strike++;
								} else { // 값이 같은 상태에서 인덱스가 다르면 볼
									ball++;
								}
							}
						}
					}
					// *** 위 for문 비교 참조! ***
					// numbers[0] == Integer.parseInt(inputNums[0]);
					// 스트라이크 +1
					// numbers[0] == Integer.parseInt(inputNums[1]);
					// numbers[0] == Integer.parseInt(inputNums[2]);
					
					// numbers[1] == Integer.parseInt(inputNums[0];
					// 볼 +1
					// numbers[1] == Integer.parseInt(inputNums[1];
					// numbers[1] == Integer.parseInt(inputNums[2];
					
					// numbers[2] == Integer.parseInt(inputNums[0];
					// numbers[2] == Integer.parseInt(inputNums[1];
					// numbers[2] == Integer.parseInt(inputNums[2];
					
					
					// 정답과 비교해서 스트라이크, 볼 알려주기
					String result = strike + "스트라이크" + ball + "볼";
					dos.writeUTF(result);
					dos.flush();
					
					// 게임종료 -> 무한반복 종료
					if(strike == 3) {
						System.out.println("아웃! 게임 종료");
						break;
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
}

✔️ 클라이언트 소켓(Client Socket) 소스코드

[Client]

package com.kh.day17.network.socket.baseball;

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 BaseballClient {

	public static void main(String[] args) {
//		클라이언트 소켓을 생성하였습니다.
//		/127.0.0.1
//		게임 준비 완료
//		--> 4 2 1
//		0스트라이크 0볼
//		--> 1 2 3
//		0스트라이크 1볼
//		--> 2 3 4
//		1스트라이크 0볼
//		--> 5 3 8
//		2스트라이크 0볼
//		--> 5 3 7
//		1스트라이크 1볼
//		--> 7 3 8
//		3스트라이크 0볼
//		축하합니다. 아웃입니다!
		
		String address = "127.0.0.1";
		int port = 8888;
		
		Scanner sc = new Scanner(System.in);
		InputStream is = null;
		OutputStream os = null;
		DataInputStream dis = null;
		DataOutputStream dos = null;
		
		try {
			// =================== 서버 연결 ===================
			Socket socket = new Socket(address, port);
			System.out.println("소켓을 생성하였습니다.");
			System.out.println("게임 준비 완료");
			
			// =============== 데이터 송수신 준비 ==============
			is = socket.getInputStream();
			os = socket.getOutputStream();
			dis = new DataInputStream(is);
			dos = new DataOutputStream(os);
			
			while(true) {
				// ================= 데이터 보내기 =================
				System.out.print("--> ");
				String input = sc.nextLine();
				dos.writeUTF(input);
				os.flush();
				
				// ================== 데이터 받기 ==================
				String recvMsg = dis.readUTF();
				System.out.println(recvMsg);
				
				// if(recvMsg.equalsIgnoreCase("3스트라이크0볼")) {
				if(recvMsg.startsWith("3")) {	// 숫자가 3으로 시작할 경우
					System.out.println("축하합니다. 맞췄습니다.");
					break;
				}
			}
			
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
profile
꾸준히

1개의 댓글

comment-user-thumbnail
2023년 7월 18일

글 잘 봤습니다, 감사합니다.

답글 달기