이롭게 현명하게

[JAVA] Study Project / UDP통신을 사용한 채팅 본문

JAVA

[JAVA] Study Project / UDP통신을 사용한 채팅

dev_y.h 2023. 1. 9. 13:51
728x90
반응형

※본 포스팅은 JDK7과 이클립스 환경에서 작성되었습니다.


UDP 통신 과정

UDP 통신을 사용하여 정해진 상대와 문자를 주고 받으며 대화를 할 수 있다. 이때 송신용 포트번호와 수신용 포트 번호가 고정되어있다. 서버 프로그램은 데이터그램 소켓을 이용하여 클라이언트 프로그램이 보낸 데이터 그램 패킷을 계속 수신한다. 패킷을 보낸 클라이언트의 인터넷 주소와 포트 번호는 패킷에서 얻을 수 있다.

 

 

다음으로 DatagramSocket 객체를 생성한다.

포트번호를 인수로 주지 않으면 비어있는 포트를 찾아 DatagramSocket객체를 만든다. 서버로 요청패킷을 만들어 전송하는 부분으로 명령어 인수로 받은 호스트 이름을 InetAddress 클래스를 이용하여 호스트 이름에 대응되는 인터넷 주소를 구한다.

final int myPort = 9102;
InetAddress address = InetAddress.getByName("127.0.0.1");
DatagramSocket socket = new DatagramSocket(myPort);

 

다음에 비어있는 배열을 패킷의 내용으로 하여 데이터 그램 패킷을 작성하여 서버로 보낸다.

String s = textField.getText();
byte[] buffer = s.getBytes();
DatagramPacket packet;		
//패킷을 생성한다.
packet = new DatagramPacket(buffer, buffer.length, address, otherPort);
try {
	socket.send(packet);
} catch (IOException e) {
	e.printStackTrace();
}

다음은 서버로부터 전송된 패킷의 내용을 화면에 보이는 부분이다.

서버로부터 응답을 받기 위하여 receive()메소드를 호출한다.

만약 패킷이 손실된 것을 알아내기 위하여 타이머를 이용하여 일정시간 이상 응답이 오지 않으면 패킷이 중간에 손실된 것으로 판단하고 서비스 요청 패킷을 다시 보낸다.

while (true) {
	try {
		byte[] buf = new byte[256];
		packet = new DatagramPacket(buf, buf.length);
		socket.receive(packet);//패킷을 받는다.
		//받은 패킷을 텍스트 영역에 표시한다.
		textArea.append("RECEIVED: "+new String(buf)+"\n");
	} catch (IOException ioException) {
		ioException.printStackTrace();
	}
}

 


MessengerA.java

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class MessengerA {
	protected JTextField textField;
	protected JTextArea textArea;
	DatagramSocket socket;
	DatagramPacket packet;
	InetAddress address = null;
	final int myPort = 9101;//수신용 포트 번호
	final int otherPort = 9102;//송신용 포트 번호
	
	public MessengerA() throws IOException{
		MyFrame f= new MyFrame();
		address = InetAddress.getByName("127.0.0.1");
		socket = new DatagramSocket(myPort);
	}
	//패킷을 받아서 텍스트 영역에 표시한다.
	public void process() {
		while (true) {
			try {
				byte[] buf = new byte[256];
				packet = new DatagramPacket(buf, buf.length);
				socket.receive(packet);//패킷을 받는다.
				//받은 패킷을 텍스트 영역에 표시한다.
				textArea.append("RECEIVED: "+new String(buf)+"\n");
			} catch (IOException ioException) {
				ioException.printStackTrace();
			}
		}
	}//채팅이 되도록함
	
	//내부 클래스 정의
	class MyFrame extends JFrame implements ActionListener{

		public MyFrame(){
			super("MessengerA");
			setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			
			textField = new JTextField(30);
			textField.addActionListener(this);
			
			textArea = new JTextArea(10,30);
			textArea.setEditable(false);
			
			add(textField,BorderLayout.PAGE_END);
			add(textArea,BorderLayout.CENTER);
			pack();
			setVisible(true);
		}
		@Override
		public void actionPerformed(ActionEvent evt) {
			String s = textField.getText();
			byte[] buffer = s.getBytes();
			DatagramPacket packet;
			
			//패킷을 생성한다.
			packet = new DatagramPacket(buffer, buffer.length, address, otherPort);
			try {
				socket.send(packet);
			} catch (IOException e) {
				e.printStackTrace();
			}
			textArea.append("SENT: "+s+"\n");
			textField.selectAll();
			textArea.setCaretPosition(textArea.getDocument().getLength());
		}
		
	}
	
	
	
	public static void main(String[] args) throws IOException {
		MessengerA m = new MessengerA();
		m.process();
	}

}

 

 

MessengerB.java

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class MessengerB {
	protected JTextField textField;
	protected JTextArea textArea;
	DatagramSocket socket;
	DatagramPacket packet;
	InetAddress address = null;
	final int myPort = 9102;//수신용 포트 번호
	final int otherPort = 9101;//송신용 포트 번호
	
	public MessengerB() throws IOException{
		MyFrame f= new MyFrame();
		address = InetAddress.getByName("127.0.0.1");
		socket = new DatagramSocket(myPort);
	}
	//패킷을 받아서 텍스트 영역에 표시한다.
	public void process() {
		while (true) {
			try {
				byte[] buf = new byte[256];
				packet = new DatagramPacket(buf, buf.length);
				socket.receive(packet);//패킷을 받는다.
				//받은 패킷을 텍스트 영역에 표시한다.
				textArea.append("RECEIVED: "+new String(buf)+"\n");
			} catch (IOException ioException) {
				ioException.printStackTrace();
			}
		}
	}//채팅이 되도록함
	
	//내부 클래스 정의
	class MyFrame extends JFrame implements ActionListener{

		public MyFrame(){
			super("MessengerB");
			setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			
			textField = new JTextField(30);
			textField.addActionListener(this);
			
			textArea = new JTextArea(10,30);
			textArea.setEditable(false);
			
			add(textField,BorderLayout.PAGE_END);
			add(textArea,BorderLayout.CENTER);
			pack();
			setVisible(true);
		}
		@Override
		public void actionPerformed(ActionEvent evt) {
			String s = textField.getText();
			byte[] buffer = s.getBytes();
			DatagramPacket packet;
			
			//패킷을 생성한다.
			packet = new DatagramPacket(buffer, buffer.length, address, otherPort);
			try {
				socket.send(packet);
			} catch (IOException e) {
				e.printStackTrace();
			}
			textArea.append("SENT: "+s+"\n");
			textField.selectAll();
			textArea.setCaretPosition(textArea.getDocument().getLength());
		}
		
	}
	
	
	
	public static void main(String[] args) throws IOException {
		MessengerB m = new MessengerB();
		m.process();
	}

}

 


잘못된 정보는 댓글에 남겨주시면 감사하겠습니다!😊

댓글과 좋아요는 큰 힘이 됩니다!

728x90
반응형
Comments