관리 메뉴

거니의 velog

230912_입출력 6 본문

대덕인재개발원_자바기반 애플리케이션

230912_입출력 6

Unlimited00 2023. 9. 11. 18:39

[TcpFileClient2.java]

package kr.or.ddit.basic.tcp;

import java.awt.Panel;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.Socket;

import javax.swing.JFileChooser;
import javax.swing.filechooser.FileNameExtensionFilter;

/*
 * 파일을 전송하는 프로그램 작성하기
 * 
 * - 클라이언트 프로그램 ==> 클라이언트 프로그램은 서버와 접속이 완료되면
 * 		'd/d_other'폴더에 있는 '펭귄.jpg'파일을 서버로 전송한다.
 * 		==> 파일 스트림으로 읽어서 소켓 스트림으로 출력한다.
 */
public class TcpFileClient2 {
	
	private void clientStart() {
		// 전송할 파일 정보를 갖는 File객체 생성
//		File file = new File("d://d_other/펭귄.jpg");
		File file = showDialog("open");
		
		if(file == null) {
			System.out.println("선택한 파일이 없습니다.");
			System.out.println("작업을 마칩니다...");
			return;
		}
		
		if(!file.exists()) {
			System.out.println(file.getPath() + " 파일이 없습니다.");
			System.out.println("작업을 중단합니다...");
			return;
		}
		
		Socket socket = null;
		BufferedInputStream bin = null;
		BufferedOutputStream bout = null;
		DataOutputStream dout = null;
		try {
			socket = new Socket("localhost", 7777);
			// "192.168.36.113"
			
			System.out.println("파일 전송 시작...");
			
			// 파일 입력용 스트림 객체 생성
			bin = new BufferedInputStream(new FileInputStream(file));
			
			// 소켓으로 출력할 스트림 객체 생성
			dout = new DataOutputStream(socket.getOutputStream());
			bout = new BufferedOutputStream(dout);
			
			// 서버에 접속하면 처음으로 파일명을 전송한다.
			dout.writeUTF(file.getName());
			
			// 파일이름 전송이 완료되면 파일의 내용을 읽어서 전송한다.
			byte[] temp = new byte[1024];
			int len = 0;
			while( (len = bin.read(temp)) != -1 ) {
				bout.write(temp, 0, len);
			}
			bout.flush();
			
			System.out.println("파일 전송 완료...");
			
		} catch (Exception e) {
//			e.printStackTrace();
			System.out.println("파일 전송 실패 : " + e.getMessage());
		} finally {
			// 스트림과 소켓 닫기
			if(dout != null) try { dout.close(); } catch (Exception e2) {}
			if(bout != null) try { bout.close(); } catch (Exception e2) {}
			if(bin != null) try { bin.close(); } catch (Exception e2) {}
			if(socket != null) try { socket.close(); } catch (Exception e2) {}
		}
	}
	
	// Dialog창을 나타내고 선택한 파일을 반환하는 메서드
	// option이 'open'이면 열기창, 'save'면 저장창을 나타낸다.
	public File showDialog(String option) {
		
		// SWING의 파일 열기, 저장 창 연습
		JFileChooser chooser = new JFileChooser();
		
		// 선택할 파일의 종류 설정하기 (파일의 확장자를 이용하여 구별한다.)
		FileNameExtensionFilter txt = new FileNameExtensionFilter("Text파일(*.txt)", "txt");
		FileNameExtensionFilter img = new FileNameExtensionFilter("그림파일", "png", "jpg", "gif");
		FileNameExtensionFilter doc = new FileNameExtensionFilter("MS Word파일", new String[] {"doc", "docx"});
		
		chooser.addChoosableFileFilter(txt);
		chooser.addChoosableFileFilter(img);
		chooser.addChoosableFileFilter(doc);
		
		// '모든 파일'이라는 항목의 표시 여부 설정 (true: 설정, false: 해제)
		// (기본값 : true)
		chooser.setAcceptAllFileFilterUsed(true);
//			chooser.setAcceptAllFileFilterUsed(false);
		
		// Dialog창에 나타날 기본 경로 설정 ('d:/d_other'로 설정하기)
		chooser.setCurrentDirectory(new File("d:/d_other"));
		
		int result;
		
		if("save".equals(option.toLowerCase())) {
			result = chooser.showSaveDialog(new Panel()); // 저장용
		}else if("open".equals(option.toLowerCase())) {
			result = chooser.showOpenDialog(new Panel()); // 열기용
		}else {
			System.out.println("option변수에는 save 또는 open만 가능합니다.");
			return null;
		}
		
		File selectedFile = null;
		
		// 창에서 '저장' 또는 '열기' 버튼을 눌렀을 때를 검사한다.
		if(result == JFileChooser.APPROVE_OPTION) {
			selectedFile = chooser.getSelectedFile();
		}
		
		return selectedFile;
		
	}
	
	public static void main(String[] args) {
		
		new TcpFileClient2().clientStart();
		
	}

}

- 서버 : java kr.or.ddit.basic.tcp.TcpFileServer2

- 클라이언트 : java kr.or.ddit.basic.tcp.TcpFileClient2


[TcpMultiChatClient.java]

package kr.or.ddit.basic.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class TcpMultiChatClient {

	public void clientStart(){
		
		try {
//			String serverIp = "localhost";
			String serverIp = "192.168.36.116";
			
			Socket socket = new Socket(serverIp, 7777);
			System.out.println("서버에 연결되었습니다.");
			System.out.println();
			
			//메시지 전송용 쓰레드 생성
			ClientSender sender = new ClientSender(socket);
			
			//메시지 수신용 쓰레드 생성
			ClientReceiver receiver = new ClientReceiver(socket);
			
			sender.start();
			receiver.start();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	public static void main(String[] args) {
		
		new TcpMultiChatClient().clientStart();
		
	}

}

//---------------------------------------
// 메시지 전송용 쓰레드
class ClientSender extends Thread{
	
	private Socket socket;
	private DataInputStream dis;
	private DataOutputStream dos;
	
	private String name;
	private Scanner scan;
	
	//생성자
	public ClientSender(Socket socket){
		this.socket = socket;
		scan = new Scanner(System.in);
		
		try {
			dis=new DataInputStream(socket.getInputStream());
			dos=new DataOutputStream(socket.getOutputStream());
			
			if(dos!=null){
				//클라이언트가 처음 실행되면 자신의 대화명(이름)을 입력받아
				//서버로 전송하고 대화명의 중복여부를 feedBack으로 받아서 확인한다.
				System.out.println("대화명: ");
				String name = scan.nextLine();
				
				while(true){
				dos.writeUTF(name); //대화명 전송
				
				//피드백을 받기 위함
				String feedBack = dis.readUTF(); //대화명 중복 여부를 받는다.
				
				if("이름중복".equals(feedBack)){//대화명이 중복되면..
					System.out.println(name + "은 대화명이 중복됩니다...");
                    System.out.println("다른 대화명을 입력하세요...");
                    
                    System.out.println("대화명: ");
					name = scan.nextLine();
					
				}else{
					this.name = name;
					System.out.println(name + "이름으로 대화방에 입장했습니다.");
					break; //반복문 탈충
				}
				
			  }
				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	@Override
	public void run() {
		try {
			while(dos != null){//전송용이기 때문에dos
				//키보드로 입력한 메시지를 서버로 전송한다.
				dos.writeUTF("[" + name + "]" + scan.nextLine());	
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

//----------------------------------------------------------------

// 메시지 수신용 쓰레드
class ClientReceiver extends Thread{
	private Socket socket;
	private DataInputStream dis;
	
	//생성자
	public ClientReceiver(Socket socket) {
		this.socket = socket;
		try {
			dis = new DataInputStream(socket.getInputStream());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		try {
			while(dis!=null){
				//서버가 보내온 메시지를 받아서 화면에 출력한다.
				System.out.println(dis.readUTF());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}

[TcpMultiChatServer.java]

package kr.or.ddit.basic.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class TcpMultiChatServer {

	// 접속한 클라이언트들을 저장할 Map객체 선언
	// ==> key값 : 접속한 사람의 이름, value값 : 접속한 클라이언트의 socket객체
	private Map<String, Socket> clientMap;
	
	//생성자
	public TcpMultiChatServer(){
		//clientMap을 동기화 처리: 동시에 여러사람이 접속하면 문제가 생길수 있기 때문
		//동기화는 쓰레드를 사용할때 이름이 같은 사람이 왔을때 첫번째 사람이 등록이 완료될때 까지 기다리는 개념
		clientMap = Collections.synchronizedMap(new HashMap<String, Socket>());
	}
		
	//clientMap에 저장된 전체 사용자에게 메시지를 전송하는 메서드
	private void sendToAll(String msg){
		//clientMap의 데이터 개수만큼 반복
		for (String name : clientMap.keySet()) {
			try {
				// 각 사용자의 소켓을 이용하여 OutputStream객체를 구한다.
				DataOutputStream dos = new DataOutputStream(
						clientMap.get(name).getOutputStream()  );
				//해당 소켓에 대한 아웃풋 스트림을 구함
				
				dos.writeUTF(msg);
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
	}
		
	public void serverStart(){
		ServerSocket server = null;
		Socket socket = null;
		
		try {
			server = new ServerSocket(7777);
			System.out.println("서버가 시작되었습니다...");
			while(true){
			   socket = server.accept(); //클라이언트의 접속을 기다린다.
			  
			   System.out.println("[" + socket.getInetAddress() + " : " + socket.getPort() + "]에서 접속을 했습니다...");
			   
			   // 메시지를 받아서 전체에게 전송하는 Thread객체를 생성하여 작동시킨다.
			   ServerReceiver serverThread = new ServerReceiver(socket);
			   serverThread.start();
			}
			
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(server != null) try { server.close(); } catch (Exception e2) {}
		}
		
	}
	
	public static void main(String[] args) {
		
		new TcpMultiChatServer().serverStart();
		
	}

	//Inner Class로 서버에서 클라이언트로 메시지를 전송하는  Thread를 만든다.
	class ServerReceiver extends Thread {
		
		private Socket socket;
		private DataInputStream dis;
		private DataOutputStream dos;
		
		//생성자
		public ServerReceiver(Socket socket) {
			this.socket = socket;
			
			try {
				//수신용 객체 생성
				dis = new DataInputStream(socket.getInputStream());
				
				//송신용 객체 생성
				dos = new DataOutputStream(socket.getOutputStream());
				
			} catch (Exception e) {
				e.printStackTrace();
			}
			
		}
		
		@Override
		public void run() {
			//이름을 받아서 클라이언트 맵에 같은 이름이 있는 경우
			//중복 여부를 클라이언트에게 보내고 (클라이언트는)새로운이름으로 등록하는 작업
			
			String name = ""; //이름 저장 변수
			try {
				while(true){
					//클라이언트가 접속이 완료되면 최초로 사용자의 이름을 전송하는데
					//이 이름이 중복되는지 여부를 feedBack으로 클라이언트에게 보내준다.
					name = dis.readUTF();
					
					if(clientMap.containsKey(name)){ //이름이 중복될때...
						dos.writeUTF("이름중복");
					}else{//이름이 중복되지 않을때...
						dos.writeUTF("OK");
						break; //반복문 탈출
					}
				}//while문 끝...
				
				// 현재 접속해 있는 다른 클라이언트들에게 대화명(이름)을 이용해서
				// 대화방 참여 메시지를 보낸다.
				sendToAll("[" + name + "]님이 대화방에 입장했습니다...");
				
				// 대화명과 클라이언트의 Socket객체를 Map에 저장한다.
				clientMap.put(name, socket);
				
				System.out.println("현재 서버 접속자 수 : " + clientMap.size() + "명");
				
				// 한 클라이언트가 보낸 메시지를 다른 클라이언트에게 전송해 준다.
				while(dis != null){
					sendToAll(dis.readUTF());//사용자에게 받아서 전체에게 보내준다.
				}
				
				
			} catch (Exception e) {
				// TODO: handle exception
			} finally{
				// 이 finally영역이 실행된다는 것은 
				// 클라이언트가 접속을 종료했다는 의미이다.
				
				// 사용자 목록에서 해당 클라이언트를 삭제한다.
				clientMap.remove(name);
				
				// 다른 사용자에게 대화방을 나갔다는 메시지 전송
				sendToAll("[" + name + "]님이 대화방을 나갔습니다...");
				
				System.out.println("[" + socket.getInetAddress() + " : " 
						+ socket.getPort() + "]에서 접속을 종료했습니다...");
				
				System.out.println("현재 서버 접속자 수 : " 
						+ clientMap.size() + "명");
				
			}
			
		}
		
	}
	
}

- 서버 : java kr.or.ddit.basic.tcp.TcpMultiChatServer

- 클라이언트 : java kr.or.ddit.basic.tcp.TcpMultiChatClient


[TcpMultiChatServer2.java]

package kr.or.ddit.basic.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class TcpMultiChatServer2 {
	
	// 접속한 클라이언트 정보(Socket객체)를 저장할 변수
	// 		=> key값 : 접속한 사람의 이름(대화명), value값 : 접속한 Socket객체
	private Map<String, Socket> clientMap;
	
	public TcpMultiChatServer2() {
		// Map객체를 동기화 처리가 되도록 생성한다.
		clientMap = Collections.synchronizedMap(new HashMap<String, Socket>());
	}
	
	// 시작 메서드
	public void serverStart() {
		
		ServerSocket server = null;
		Socket socket = null;
		
		try {
			server = new ServerSocket(7777);
			System.out.println("채팅 서버가 시작되었습니다...");
			
			while(true) {
				socket = server.accept(); // 클라이언트의 접속을 기다린다.
				System.out.println("[" + socket.getInetAddress() + " : " + socket.getPort() + "] 에서 접속했습니다...");
				System.out.println();
				///////////////////////////////////
				
				// 쓰레드 객체 생성 및 실행
				ServerReceiver serverThread = new ServerReceiver(socket);
				serverThread.start();
			}
			
		} catch (Exception e) {
//			e.printStackTrace();
		}
		
	} // 시작 메서드 끝...

	// Map에 저장된 전체 클라이언트들에게 메시지를 전송하는 메서드
	private void sendToAll(String msg) {
		// Map의 데이터 개수만큼 반복
		for(String name : clientMap.keySet()) {
			try {
				// 각 key 값에 대응하는 Socket 객체의 출력용 스트림 객체를 구해서 사용한다.
				DataOutputStream dout = new DataOutputStream(clientMap.get(name).getOutputStream());
				// 출력용 스트림을 이용해서 메시지를 전송(출력)한다.
				dout.writeUTF(msg);
				
			} catch (Exception e) {
//				e.printStackTrace();
			}
		}
	} // sendToAll() 메서드 끝...
	
	public static void main(String[] args) {
		
		new TcpMultiChatServer2().serverStart();
		
	}
	
	//------------------------------------------------------------
	// 서버에서 각 클라이언트로 메시지를 전송하는 Thread를 Inner Class로 작성한다.
	// 		==> Inner Class를 사용하는 이유 ( Outer Class의 멤버 변수를 자유롭게 사용할 수 있다. )
	class ServerReceiver extends Thread {
		
		private Socket socket;
		private DataInputStream din;
		private DataOutputStream dout;
		
		// 생성자
		public ServerReceiver(Socket socket) {
			this.socket = socket;
			try {
				// 수신용 스트림 객체 생성
				din = new DataInputStream(this.socket.getInputStream());
				
				// 송신용 스트림 객체 생성
				dout = new DataOutputStream(this.socket.getOutputStream());
				
			} catch (Exception e) {
//				e.printStackTrace();
			}
		} // 생성자 끝...

		@Override
		public void run() {
			String name = "";
			try {
				// 클라이언트가 연결이 성공하면 클라이언트는 첫 번째 데이터로 '대화명'을 입력 받아서 보낸다.
				// 서버에서는 이 '대화명'을 받아서 '대화명'이 중복되는지 여부를 검사해서 그 결과를 응답으로 클라이언트에게 보내준다.
				
				// 클라이언트가 보내온 '대화명'이 중복되지 않을 때까지 반복한다.
				while(true) {
					name = din.readUTF(); // 클라이언트가 보낸 '대화명' 받기
					
					if(clientMap.containsKey(name)) { // '대화명'이 중복되면...
						dout.writeUTF("대화명중복"); // 응답으로 '대화명중복' 메시지 전송
					}else { // '대화명'이 중복되지 않으면...
						dout.writeUTF("OK"); // 응답으로 'OK' 메시지 전송
						break; // 반복문 탈출
					}
				} // while문 끝...
				
				// 접속한 사람의 대화명을 이용하여 다른 전체 클라이언트들에게 대화방에 참여한다는 메시지를 보낸다.
				sendToAll("[" + name + "] 님이 대화방에 입장했습니다...");
				
				// 대화명을 key값으로 클라이언트의 Socket객체를 Map에 추가한다.
				clientMap.put(name, socket);
				
				System.out.println("현재 접속자 수 : " + clientMap.size() + "명");
				System.out.println();
				
				// 현 클라이언트가 보낸 메시지를 받아서 전체 클라이언트에게 다시 보낸다.
				while(din != null) {
					sendToAll(din.readUTF());
				}
				
			} catch (Exception e) {
//				e.printStackTrace();
			} finally {
				// 이 finally 영역이 실행된다는 것은 현 클라이언트가 접속을 종료했다는 의미이다.
				sendToAll("[" + name + "] 님이 접속을 종료했습니다...");
				
				// Map에서 해당 클라이언트 정보를 삭제한다.
				clientMap.remove(name);
				System.out.println();
				
				System.out.println("[" + socket.getInetAddress() + " : " + socket.getPort() + "] 에서 접속을 종료했습니다...");
				System.out.println();
				
				System.out.println("현재 접속자 수 : " + clientMap.size() + "명");
				System.out.println();
			}
		}
		
	}
	
}

[TcpMultiChatClient2.java]

package kr.or.ddit.basic.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.Scanner;

public class TcpMultiChatClient2 {

	public static void main(String[] args) {
		
		new TcpMultiChatClient2().clientStart();
		
	}
	
	// 시작 메서드
	public void clientStart() {
		
		Socket socket = null;
		try {
			socket = new Socket("localhost", 7777);
			System.out.println("서버에 접속했습니다...");
			System.out.println();
			//////////////////////////////////////////////
			// 전송용 쓰레드 객체 생성
			ClientSender sender = new ClientSender(socket);
			
			// 수신용 쓰레드 객체 생성
			ClientReceiver receiver = new ClientReceiver(socket);
			
			sender.start();
			receiver.start();
			
		} catch (Exception e) {
//			e.printStackTrace();
		}
		
	} // 시작 메서드 끝...
	
	//-------------------------------------------
	// 메시지를 전송하는 전송용 쓰레드
	class ClientSender extends Thread {
		
		private Socket socket;
		private DataOutputStream dout;
		private DataInputStream din;
		
		private String name; // 대화명이 저장될 변수
		private Scanner scan;
		
		// 생성자
		public ClientSender(Socket socket) {
			this.socket = socket;
			scan = new Scanner(System.in);
			
			try {
				din = new DataInputStream(this.socket.getInputStream()); // 수신용
				dout = new DataOutputStream(this.socket.getOutputStream()); // 송신용
				
				if(din != null) {
					while(true) {
						// 클라이언트는 처음 실행하면 서버에서 접속하고 접속에 성공하면 첫번째로 '대화명'을 입력받아 전송하고, 이 '대화명'의 중복 여부를 응답으로 받아서 확인한다.
						System.out.print("대화명 >> ");
						String name = scan.nextLine();
						dout.writeUTF(name); // 입력받은 '대화명'을 서버로 전송하기
						
						// '대화명'의 중복 여부를 응답으로 받는다.
						String feedBack = din.readUTF();
						
						if("대화명중복".equals(feedBack)) { // '대화명'이 중복될 때...
							System.out.println(name + "은(는) 대화명이 중복됩니다...");
							System.out.println("새로운 대화명을 입력하세요...");
						}else { // '대화명'이 중복되지 않을 때...
							this.name = name;
							System.out.println("[" + name + "] 대화명으로 대화방에 입장했습니다...");
							break; // 반복문 탈출...
						}
					} // while문 끝...
					
				} // if문 끝...
				
			} catch (Exception e) {
//				e.printStackTrace();
			}
		} // 생성자 끝...
		
		@Override
		public void run() {
			try {
				while(dout != null) {
					// 키보드로 입력한 메시지를 서버로 전송한다.
					dout.writeUTF("[" + name + "] " + scan.nextLine());
				}
				
			} catch (Exception e) {
//				e.printStackTrace();
			}
		}
		
	} // 전송용 쓰레드 끝...
	
	//-------------------------------------------
	// 메시지를 받아서 화면에 출력하는 쓰레드
	class ClientReceiver extends Thread {
		
		private Socket socket;
		private DataInputStream din;
		
		// 생성자
		public ClientReceiver(Socket socket) {
			this.socket = socket;
			try {
				din = new DataInputStream(this.socket.getInputStream());
			} catch (Exception e) {
//				e.printStackTrace();
			}
		} // 생성자 끝...
		
		@Override
		public void run() {
			try {
				while(din != null) {
					// 서버가 보내온 메시지를 받아서 화면에 출력한다.
					System.out.println(din.readUTF());
				}
			} catch (Exception e) {
//				e.printStackTrace();
			}
		}
		
	}
	
}

- 서버 : java kr.or.ddit.basic.tcp.TcpMultiChatServer2

- 클라이언트 : java kr.or.ddit.basic.tcp.TcpMultiChatClient2


[UdpServer.java]

package kr.or.ddit.basic.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/*
 * UDP방식 : 비연결 지향, 신뢰성이 없다. 데이터가 순서대로 도착한다는 보장이 없다.
 * 			그렇지만 TCP방식보다 속도가 빠르다.
 * 
 * DatagramSocket객체와 DatagramPacket객체를 이용하여 통신한다.
 * - DatagramSocket객체 ==> 데이터의 송수신과 관련된 작업을 수행한다. (우체부 역할)
 * - DatagramPacket객체 ==> 주고 받는 실제 데이터와 관련된 작업을 수행한다. (편지, 소포 역할)
 * 			==> 수신용을 위한 생성자와 송신용을 위한 생성자를 따로 제공한다.
 * 
 * TCP는 스트림을 이용해서 데이터를 송수신 하지만
 * UDP는 데이터그램을 이용하여 데이터를 송수신 한다.
 * 
 * 클라이언트에게 받은 데이터를 클라이언트에게 다시 돌려주는 에코 프로그램 작성
 */
public class UdpServer {

	public static void main(String[] args) {
		
		try {
			// 통신할 포트를 지정하여 소켓 객체를 생성한다.
			DatagramSocket socket = new DatagramSocket(8888);
			
			// 수신용 패킷 객체 변수와 송신용 패킷 객체 변수 선언
			DatagramPacket inpacket, outpacket;
			System.out.println("서버 실행 중...");
			
			while(true) {
				// 상대방이 보낸 자료를 받아 오기
				
				// 수신 받은 데이터가 저장될 byte형 배열 선언
				byte[] bMsg = new byte[512];
				
				// 수신용 패킷 객체 생성
				// ==> 데이터가 저장될 byte형 배열과 그 배열의 길이를 생성자의 인수값으로 지정하여 수신용 패킷 객체를 생성한다.
				inpacket = new DatagramPacket(bMsg, bMsg.length);
				
				// 데이터를 수신한다. ==> 소켓의 receive() 메서드를 이용한다.
				// receive()메서드는 데이터가 올 때까지 기다린다.
				// 수신된 데이터의 패킷 정보는 수신용 패킷 객체를 생성할 때 생성자에 지정한 패킷 객체에 저장된다. 
				socket.receive(inpacket);
				
				// 수신 받은 패킷에서 상대방의 주소 정보, 포트 번호 등을 알 수 있다.
				InetAddress address = inpacket.getAddress();
				int port = inpacket.getPort();
				System.out.println("상대방의 IP정보 : " + address);
				System.out.println("상대방의 Port번호 : " + port);
				System.out.println();
				
				// 상대방이 보낸 메시지 출력하기
				// 수신용 패킷 객체.getData() ==> 실제 수신한 데이터를 byte형 배열로 반환한다.
				// 		==> 수신용 패킷 객체를 생성할 때 지정한 byte형 배열에 수신한 데이터가 저장된다.
				// 수신용 패킷 객체.getLength() ==> 실제 수신한 데이터의 길이 반환.
				
				// byte형 배열 자료를 String으로 변환한다.
//				String msg = new String(bMsg, 0, inpacket.getLength(), "utf-8");
				String msg = new String(inpacket.getData(), 0, inpacket.getLength(), "utf-8");
				
				if("/end".equals(msg) ) {
					break;
				}
				
				System.out.println("상대방이 보낸 메시지 : " + msg);
				System.out.println();
				
				////////////////////////////////////
				// 상대방에게 메시지 보내기 ( 수신 받은 메시지를 그대로 송신하기 )
				
				// 송신할 메시지를 byte형 배열로 변환한다.
				byte[] sendMsg = msg.getBytes("utf-8");
				
				// 송신용 패킷 객체 생성
				// 		==> 전송할 데이터가 저장된 byte형 배열, 전송할 자료의 길이(배열의 길이), 
				// 			상대방의 주소 정보, 포트번호 
				// 			이렇게 4가지를 지정하여 객체를 생성한다.
				outpacket = new DatagramPacket(sendMsg, sendMsg.length, address, port);
				
				// 데이터 송신하기 ==> 소켓객체의 send()메서드 이용
				socket.send(outpacket);
				System.out.println("송신 완료...");
				System.out.println();
			} // while문 끝...
			
		} catch (Exception e) {
			// TODO: handle exception
		}
		
	}

}

[UdpClient.java]

package kr.or.ddit.basic.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;

public class UdpClient {

	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);
		
		// 수신 받은 데이터가 저장될 byte형 배열 선언
		byte[] bMsg = new byte[512];
		
		try {
			DatagramSocket socket = new DatagramSocket();
			
			// 접속할 상대방의 주소 정보 생성
			InetAddress address = InetAddress.getByName("127.0.0.1");
//			InetAddress address = InetAddress.getByName("localhost");
			
			// 수신용, 송신용 패킷 객체 변수 선언
			DatagramPacket inpacket, outpacket;
			
			while(true) {
				// 전송할 메시지를 입력 받는다.
				System.out.print("보낼 메시지 입력 >> ");
				String msg = scan.nextLine();
				
				// 전송용(송신용) 패킷 객체 생성
				outpacket = new DatagramPacket(msg.getBytes("utf-8"), msg.getBytes("utf-8").length, address, 8888);
				
				// 데이터 전송
				socket.send(outpacket);
				
				if("/end".equals(msg)) { // 입력한 메시지가 '/end'이면 작업을 마친다.
					break;
				}
				// ---------------------------------------------------
				
				// 서버에서 온 데이터를 받아서 출력하기
				
				// 수신용 패킷 객체 생성
				inpacket = new DatagramPacket(bMsg, bMsg.length);
				
				// 데이터 수신
				socket.receive(inpacket);
				
				String receiveMsg = new String(inpacket.getData(), 0, inpacket.getLength(), "utf-8");
				
				System.out.println("서버의 응답 메시지 >> " + receiveMsg);
				System.out.println();
				
			} // while문 끝...
			
			System.out.println("작업 끝...");
			
		} catch (Exception e) {
			// TODO: handle exception
		}
		
	}

}

- 서버 : java kr.or.ddit.basic.udp.UdpServer

- 클라이언트 : java kr.or.ddit.basic.udp.UdpClient

'대덕인재개발원_자바기반 애플리케이션' 카테고리의 다른 글

230914_JDBC 2  (0) 2023.09.14
230913_JDBC 1  (0) 2023.09.12
230911_입출력 5  (0) 2023.09.11
230908_입출력 4  (0) 2023.09.08
230907_입출력 3  (2) 2023.09.07