-
- UDP(User Datagram Protocol) : 발신자가 일방적으로 수신자에게 데이터를 보내는 방식
- 장점
TCP와 달리 연결 요청 및 연결 수략 과정이 없기 때문에 상대적으로 데이터 전송 속도가 빠르다. - 단점
데이터 전송 회선이 고정되지 않기 때문에 데이터 손실되거나 데이터의 순서가 섞일 수 있다. - 데이터 전달의 신뢰성보다 속도가 중요한 통신에서 사용
- 실시간 영상 송출 등 - 자바에서 DatagramSocket과 DatagramPacket 클래스(java.net)를 통해 UDP 네트워킹을 지원한다.
- DatagramSocket
- 발신점과 수신점을 담당 - DatagramPacket
- 데이터 송수신에 관여
- DatagramSocket
UDP 서버
- 서버는 항상 클라이언트가 보낼 DatagramPacket을 받을 준비를 해야 한다.
//송수신 포트를 지정하여 DatagrameSocket 객체 생성DatagramSocket datagrameSocket = new DatagramSocket(50001);- recevie() 메소드를 이용해 데이터를 받는다.
- 데이터를 받을 수 있는 비어있는 DatagramPacket 객체를 미리 준비해두었다가 데이터가 들어올 때 받아내는 방식이다.
- 데이터를 수신할 때까지 블로킹된다.
//클라이언트가 보낸 데이터를 받아낼 DatagramPacket 준비DatagramPacket datagramPacket = new DatagramPacket(new byte[1024], 1024); //수신한 바이트 데이터를 저장할 배열과 최대 수신할 수 있는 바이트 수를 매개값으로 설정datagramPacket.receive(receivePacket); //receive() 메소드로 데이터를 수신- receive 메소드를 실행하여 받은 데이터 정보를 얻는 방법
//receive 메소드가 실행된 이후 수쇤된 바이트 데이터 확인byte[] bytes = receivePacket.getData(); //수신한 바이트 데이터를 저장int num = receivePacket.getLength(); //실제로 읽은 바이트 수를 리턴//받은 바이트 데이터를 문자열로 변환Stirng data = new String(bytes, 0, num, "UTF-8"); //실제로 읽은 바이트 수만큼만 문자열로 변환해야 함- TCP 통신에서는 서버의 IP 주소와 포트 번호만 알아도 데이터 송수신이 가능했지만 UDP 통신에서는 서버와 연결 요청/수락 과정이 없기 때문에 서버에서 클라이언트로 메시지를 보내기 위해서는 클라이언트의 IP 주소와 포트 번호도 알아야 한다.
- DatagramPacket에는 데이터를 송신한 쪽(클라이언트)의 IP 정보와 포트 정보가 들어있으며, 이를 이용해 데이터를 보낸 쪽에 응답 데이터를 보낼 수 있다.
//데이터를 보낸 쪽의 IP와 포트 정보를 추출SocketAddress socketAddress = receivePacket.getSocketAddress();//클라이언트로부터 받은 데이터에 대한 처리 내용을 보내기 위해 준비하는 과정String data = "처리 내용";byte[] bytes = data.getBytes("UTF-8");DatagramPacket sendPacket = new DatagramPacket(bytes, 0, bytes.length, socketAddress);//전송할 바이트 배열의 길이만 입력해도 0 인덱스부터 데이터를 읽어서 DatagramPacket 갱체 생성 가능DatagramPacket sendPacket = new DatagramPacket(bytes, bytes.length, socketAddress);//DatagramPacket에 담은 데이터를 DatagramSocket 객체를 통해 전송datagramSocket.send(sendPacket);- UDP 서버 종료
//UDP 서버 종료datagramSocket.close();
UDP 클라이언트
- 서버에 요청 내용을 보내고 서버에서 처리한 결과를 받는 역할
- Port 번호는 내부적으로 자동 부여되기 때문에 DatagramSocket 객체를 기본 생성자로 생성
//기본 생성자로 DatagramSocket 객체 생성DatagramSocket datagramSocket = new DatagramSocket();- 생성한 DatagramPacket 객체에 요청 내용을 저장하여 서버에 전송
//요청 내용을 담을 DatagramPacket 객체 생성String data = "요청 내용";byte[] bytes = dat.getBytes("UTF-8");DatagramPacket sendPacket = new DatagramPacket(bytes, bytes.length, new InetSocketAddress("localhost", 50001));//DatagramSocket을 통해 요청 내용을 서버에 전송datagramSocket.send(sendPacket);- 더 이상 서버에서 보내는 데이터를 그만 받으려면 DatagramSocket을 종료하면 된다.
//UDP 통신 종료.datagramSocket.close();
UDP 통신 프로그램 예제
- 클라이언트로부터 구독할 주제를 받으면 10개의 뉴스를 제공하는 프로그램
서버 프로그램
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475public class NewsServer {private static DatagramSocket datagramSocket;//클라이언트에게 뉴스를 반복적으로 보내는 서버 프로그램public static void main(String[] args) {System.out.println("------------------------------------------------------------");System.out.println("서버를 종료하려면 q 또는 Q를 입력하고 Enter키를 입력하세요.");System.out.println("------------------------------------------------------------");//UDP 서버 시작startServer();//키보드 입력Scanner scanner = new Scanner(System.in);while(true) {String key = scanner.nextLine();if(key.toLowerCase().equals("q")) { //대소문자 구분없이 인식break;}}scanner.close();//UDP 서버 종료stopServer();}public static void startServer() {//작업 스레드 정의Thread thread = new Thread() {@Overridepublic void run() {try {//DatagramSocket 생성 및 Port 바인딩datagramSocket = new DatagramSocket(50001);System.out.println("[서버] 시작됨");while(true) {//클라이언트가 구독하고 싶은 뉴스 주제 얻기DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024); //읽을 수 있는 최대 바이트 수는 저장할 수 있는 바이트 수를 초과할 수 없다.System.out.println("클라이언트의 희망 뉴스 종류 얻기위해 대기");datagramSocket.receive(receivePacket);String newsKind = new String(receivePacket.getData(), 0, receivePacket.getLength(), "UTF-8");//클라이언트의 IP와 Port 정보가 있는 SocketAddress 얻기SocketAddress socketAddress = receivePacket.getSocketAddress();//10의 뉴스를 클라이언트로 전송for(int i=1; i<=10; i++) {String data = newsKind + ": 뉴스" + i;byte[] bytes = data.getBytes("UTF-8");DatagramPacket sendPacket = new DatagramPacket(bytes, 0, bytes.length, socketAddress);datagramSocket.send(sendPacket);Thread.sleep(1000); //뉴스 전송 간격 추가}}} catch (Exception e) {System.out.println("[서버] " + e.getMessage());}}};//작업 스레드 시작thread.start();}public static void stopServer() {//DatagramSocket을 단고 Port 언바인딩datagramSocket.close();System.out.println("[서버] 종료됨");}}클라이언트 프로그램
123456789101112131415161718192021222324252627282930313233343536373839public class NewsClient {public static void main(String[] args) {try {//DatagramSocket 생성DatagramSocket datagramSocket = new DatagramSocket();//구독하고 싶은 뉴스 주제 보내기String data = "정치";byte[] bytes = data.getBytes("UTF-8");DatagramPacket sendPacket = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress("localhost", 50001));datagramSocket.send(sendPacket);while(true) {//뉴스 받기DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);datagramSocket.receive(receivePacket);//문자열로 변환String news = new String(receivePacket.getData(), 0, receivePacket.getLength(), "UTF-8");System.out.println(news);//10번째 뉴스를 받으면 while 문을 종료if(news.contains("뉴스10")) {break;}}//DatagramSocket 닫기datagramSocket.close();} catch (Exception e) {System.out.println(e.getMessage());}}}실행 결과