시소당
이번 시간에는 자바에서 Datagram을 다루는 것에 대해 보도록 하겠습니다. 즉 TCP와 대비되는 UDP와 관련된 부분 입니다.
UDP( User Datagram Protocol )
? UDP 는 TCP 와 달리 스트림 기반이 아니며 TCP 와 같이 IP 를 사용하여 데이터를 전송하며 매우 신속 하지만 신뢰성은 없습니다.
? TCP 는 패킷을 직접 다루지 않으며 스트림을 통해 간접적 으로 패킷의 전송을 다루므로 패킷의 전송에 거의 신경 쓸 일이 없으나 UDP 는 패킷을 직접 다루는 프로토콜 입니다.
? TCP 는 가상적인 연결 (Connection) 이 있어야 데어터를 보 낼 수 있지만 UDP 의 경우 목적지를 명시한 패킷을 네트 웍 상에 흘려 놓거나 언젠가 도착 할 패킷을 마냥 기다리고 있을 뿐 입니다.
? UDP 프로토콜은 데이터그램이라는 데이터 패킷을 사 용하는데 , 데이터그램 패킷 들은 서로 내용이 독립적 이며 자체 내에 목적지에 대한 정보를 갖고 송신자로 부터 수신자로 전공 됩니다.
? UDP 는 메시지가 제대로 도착했는지 확인하는 확인 응 답을 사용하지 않을 뿐만 아니라 , 수신된 메시지의 순 서를 맞추지 않으며 , 기계간의 정보 흐름 속도를 제어 하기 위한 피드백을 제공하지 않기 때문에 UDP 메시 지는 손실되거나 , 중복되거나 , 비순서적으로 도착될 수 있습니다.
? UDP 는 IP 상에 패킷을 흘려 놓은 후 TCP 와 같이 확실히 도착 했는지의 여부를 검사하지 않으며 TCP 의 경우 도중에 패킷이 유실되면 다시 전송하도록 하 며 패킷의 순서가 뒤섞인 채 전송되면 패킷을 제대로 된 순 서로 정리하지만 UDP는 그렇지 않습니다. TCP 의 경우 라우터 처리용량에 여유가 없을 때는 패킷을 잘게 나누어 다시 재 시도 되기 때문에 어느 정도는 안전한 방법이나 UDP 의 경우 라우터가 패킷을 거부하면 그 패킷 은 버려지게 됩니다.
? UDP 패킷의 크기를 잘 조정 하는 것은 프로그래머가 해줘 야 할 일 입니다.
? UDP 는 예전에 멀티미디어 스트리밍 서비스와 같이 소리나 화면이 잠깐 끊어져도 문제되지 않는 곳에 사용되었으나 근래에는 QoS(Quality of Service) 의 문제로 인해 멀티미디어 스트리밍에도 잘 쓰이지 않습니다.
? UDP 는 작고 가벼우며 빠르기 때문에 router 를 벗어나 지 않는 내부 네트웍용으로 많이 사용 됩니다.
아래는 Datagran에 관한 건데 참고로 읽어 보세요~(영어는 잘 되시죠^^;)
? The UDP protocol provides a mode of network communication whereby applications send packets of data, called datagrams, to one another.
? A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed.
결국 TCP는 신뢰할 수 있는 네트웍, 즉 데이터를 보내기 전에 연결을 설정하여 데이터를 보내고 또한 데이터가 잘 갔는지 확인하며 오류제어도 하면서 순서가 뒤틀리면 받는데서 정리도 하는 것임에 반해 UDP는 지나가는 강아지의 목에 주소만 써서 편지를 배달하는 것과 같이 전송을 보장 하지 않는 대신에 TCP보다는 빠른 프로토콜 입니다.
DatagramSocket
? DatagramPacket 객체를 전송하고 수신하는데 사용되며, 즉 DatagramPacket 을 사용하기 위해서는 DatagramSocket 을 생성해야 한다는 겁니다.
? DatagramSocket 객체 하나만 가지고도 여러 목적지로 패킷을 보낼 수 있으며 여러 발신지로 부터 패킷을 받을 수 있습니다. 어느 호스트로 부터 패킷을 받을지 정하는 방법은 없습니다.
? 대개 모든 DatagramSocket 은 하나의 Local port 에서 돌아 가며 이 port 에서 Socket 은 Host 로 들어오는 데이터를 기다리고 Network 으로 나가는 Datagram 에 헤더를 붙입니다.
? DatagramSocket 은 로컬호스트의 어떤 UDP Port 에서 패킷이 날아 오기만 기다리고 있으며 대개의 경우 서버 프로그램은 포트를 지정해 주며 클라이언트 프로그램의 경우 UDP 포트를 시스템에서 임의로 지정하게 하는 방식을 사용 합니다.
? TCP 처럼 Server 와 Client 별개의 소켓을 가지고 있지 않습니다.
? DatagramSocket 은 TCP 방식과는 달리 서버와 클라이언트가 동일하게 사용하며 , 먼저 서버측에서 소켓을 생성하여 대기하면 클라이언트가 소켓을 생성하여 데 이터를 전송을 하는 것입니다.
? UDP 서버와 TCP 서버는 같은 포트를 사용 할 수 있습니다.
다음은 생성자 입니다.
? DatagramSocket()
? Constructs a datagram socket and binds it to any available port on the local host machine.
? DatagramSocket(int port)
? Constructs a datagram socket and binds it to the specified port on the local host machine.
? DatagramSocket(int port, InetAddress laddr)
? Creates a datagram socket, bound to the specified local address.
? 보통 여러 개의 NIC(Network Interface Card) 가 꽃힌 컴퓨 터의 로컬 주소와 DatagramSocket 을 바인딩
DatagramPacket 클래스
? 하나의 데이터그램 패킷을 캡슐화
? 메시지 몸체와 목적지 주소로 구성
? DatagramPacket 클래스는 데이터그램을 사용할 수 있도록 기능을 제공해 주며 , 데이터그램 패킷은 비연결 패킷 전송 서비스 (connectionless packet delivery service) 를 구현하기 위해 사용 됩니다. 메시지는 패킷 내에 포함되어 있는 정보에 기반 하여 하나의 호스트에서 다른 호스트로 라우팅 됩니다.
? 한 호스트에서 다른 호스트로 전송된 여러 개의 패킷 (multiple packet) 은 서로 다르게 라우팅 될 것이며 , 원래의 순서와 관계없이 도착될 수 있습니다. 결국 DatagramPacket은 비연결 지향 패킷을 구현 했다고 보면 되겠네요...
생성자는 다음과 같습니다.
? DatagramPacket(byte[] buf, int length)
? Constructs a DatagramPacket for receiving packets of length length.
? buf 는 수신되는 UDP 패킷을 받아 낼 바이트 배열
? DatagramPacket(byte[] buf, int length, InetAddress address, int port)
? Constructs a datagram packet for sending packets of length length to the specified port number on the specified host.
다음은 데이터 송수신 순서 입니다. 잘보도록 하죠...
1. 서버는 클라이언트로부터 요청을 받고 그에 대해 응답을 하 기 위한 데이터그램 소켓을 생성하여 특정 포트에 연결 합니다 .
2 서버는 클라이언트로부터 오는 요청 내용을 저장할 입력 데이터그램 패킷을 생성한 뒤 클라이언트로부터 요청이 오기를 기다리며 대기 합니다.
3. 클라이언트 프로그램을 실행하면 서버에서와 마찬가지로 데이터그램 소켓을 하여 특정 포트에 연결 합니다.
4. 클라이언트 는 서버에 요청을 보내기 위한 출력 데이터그램 패킷을 생성한 뒤 서버에게 송신 합니다.
5. 서버는 클라이언트가 보낸 데이터그램 패킷을 받아 들이는데 여기서 서버는 이미 입력 데이터그램 패킷을 생성하고 대기하였는데 , 이 입력 데이터그램 패킷은 아무런 내용이 없는 빈 패킷으로서 이 패킷이 클라이언트가 보낸 데이터그램 패킷으로 대치 됩니다 . 따라서 서버 자신이 생성한 입력 데이터그램 패킷을 받는 것 자체가 곧 클라이언트가 보낸 데이터그램 패킷을 받는 것과 동일한 효과를 나타낸다 .
6. 클라이언트도 서버가 보낸 응답을 받기 위한 입력 데이터그 램 패킷을 생성하고 대기 합니다.
[ UDPDaytimeServer.java] -- 데이터그램서버 프로그램 입니다. 실행시 별다른 인자없이 실행하시면 됩니다.
import java.net.*;
import java.io.*;
import java.util.Date;
public class UDPDaytimeServer {
public static final int DAYTIME_PORT = 13;
public static void respond(DatagramSocket ds, DatagramPacket dp) {
DatagramPacket outgoing;
Date now = new Date();
String s = now.toString();
byte[] data = s.getBytes();
try {
outgoing = new DatagramPacket(data, data.length, dp.getAddress(), dp.getPort());
ds.send(outgoing);
}
catch (IOException e) {
System.err.println(e);
}
}
public static void main(String args[]) {
try {
DatagramSocket ds = new DatagramSocket(DAYTIME_PORT);
DatagramPacket incoming;
byte[] buffer = new byte[2048];
while(true) {
incoming = new DatagramPacket(buffer, buffer.length);
ds.receive(incoming);
respond(ds, incoming);
}
} catch(IOException e) {
System.out.println(e);
}
}
}
[ Daytime.java] -- 데이터그램 클라이언트 프로그램 입니다. 실행시 인자로 loclahost 정도 줘서 실행하시면 됩니다. java Daytime localhost
import java.io.*;
import java.net.*;
public class Daytime {
public static final int DAYTIME_PORT = 13;
public static final String getTime(String hostname) throws IOException {
InetAddress host;
DatagramSocket socket = new DatagramSocket();
byte[] dummyData = new byte[1];
byte[] timeData = new byte[256];
DatagramPacket sendPacket, receivePacket;
host = InetAddress.getByName(hostname);
sendPacket =
new DatagramPacket(dummyData, dummyData.length, host, DAYTIME_PORT);
receivePacket = new DatagramPacket(timeData, timeData.length);
socket.send(sendPacket);
socket.receive(receivePacket);
return
new String(receivePacket.getData(), 0, receivePacket.getLength());
}
public static void main(String[] args) {
String server = "localhost";
if(args.length == 1)
server = args[0];
else if(args.length > 1) {
System.err.println("Usage: Daytime [hostname]");
return;
}
try {
// Time should include newline, so we don't use println().
System.out.print(getTime(server));
System.out.flush();
} catch(IOException e) {
e.printStackTrace();
return;
}
}
}
[Daytime 실행 결과 입니다.]
다음은 위의 예제와 비숫하지만 올려 봅니다. 따라해 보세요
[DatagramServer.java]
import java.io.*;
import java.net.*;
public class DatagramServer {
public static void main(String[] args) {
DatagramPacket packet = null;
byte[] b = new byte[256];
try {
DatagramSocket socket = new DatagramSocket(4444);
while(true) {
packet = new DatagramPacket(b, b.length);
// 패킷을 받아서 데이터를 received 문자열에 넣음.
socket.receive(packet);
String received = new String(packet.getData());
// 데이터를 바이트배열로 전환하여 패킷으로 다시 보냄.
InetAddress address = packet.getAddress();
int port = packet.getPort();
b = received.getBytes();
packet = new DatagramPacket(b, b.length, address, port);
socket.send(packet);
}
} catch(IOException ex) {
ex.printStackTrace();
}
}
}
[DatagramClient.java]
import java.io.*;
import java.net.*;
public class DatagramClient {
public static void main(String[] args) {
byte[] b = new byte[256];
String send = null;
DatagramPacket packet = null;
try {
DatagramSocket udpSocket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName(args[0]);
BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
System.out.print("send... ");
while ((send = in.readLine()) != null) {
// 문자열을 바이트배열로 전환한 후 포트 4444로 전송한다.
b = send.getBytes();
packet = new DatagramPacket(b, send.length(), serverAddress, 4444); //송신용 패킷
//packet.setLength(b.length);
udpSocket.send(packet);
// 패킷을 수신하여 문자열로 전환한 후 화면에 출력한다.
packet = new DatagramPacket(b, b.length);
udpSocket.receive(packet);
String received = new String(packet.getData());
System.out.println("receive... " + received);
System.out.print("send... ");
}
udpSocket.close();
} catch(IOException ex) {
ex.printStackTrace();
}
}
}
이번 시간에는 자바에서 Datagram을 다루는 것에 대해 보도록 하겠습니다. 즉 TCP와 대비되는 UDP와 관련된 부분 입니다.
UDP( User Datagram Protocol )
• UDP 는 TCP 와 달리 스트림 기반이 아니며 TCP 와 같이 IP 를 사용하여 데이터를 전송하며 매우 신속 하지만 신뢰성은 없습니다.
• TCP 는 패킷을 직접 다루지 않으며 스트림을 통해 간접적 으로 패킷의 전송을 다루므로 패킷의 전송에 거의 신경 쓸 일이 없으나 UDP 는 패킷을 직접 다루는 프로토콜 입니다.
• TCP 는 가상적인 연결 (Connection) 이 있어야 데어터를 보 낼 수 있지만 UDP 의 경우 목적지를 명시한 패킷을 네트 웍 상에 흘려 놓거나 언젠가 도착 할 패킷을 마냥 기다리고 있을 뿐 입니다.
• UDP 프로토콜은 데이터그램이라는 데이터 패킷을 사 용하는데 , 데이터그램 패킷 들은 서로 내용이 독립적 이며 자체 내에 목적지에 대한 정보를 갖고 송신자로 부터 수신자로 전공 됩니다.
• UDP 는 메시지가 제대로 도착했는지 확인하는 확인 응 답을 사용하지 않을 뿐만 아니라 , 수신된 메시지의 순 서를 맞추지 않으며 , 기계간의 정보 흐름 속도를 제어 하기 위한 피드백을 제공하지 않기 때문에 UDP 메시 지는 손실되거나 , 중복되거나 , 비순서적으로 도착될 수 있습니다.
• UDP 는 IP 상에 패킷을 흘려 놓은 후 TCP 와 같이 확실히 도착 했는지의 여부를 검사하지 않으며 TCP 의 경우 도중에 패킷이 유실되면 다시 전송하도록 하 며 패킷의 순서가 뒤섞인 채 전송되면 패킷을 제대로 된 순 서로 정리하지만 UDP는 그렇지 않습니다. TCP 의 경우 라우터 처리용량에 여유가 없을 때는 패킷을 잘게 나누어 다시 재 시도 되기 때문에 어느 정도는 안전한 방법이나 UDP 의 경우 라우터가 패킷을 거부하면 그 패킷 은 버려지게 됩니다.
• UDP 패킷의 크기를 잘 조정 하는 것은 프로그래머가 해줘 야 할 일 입니다.
• UDP 는 예전에 멀티미디어 스트리밍 서비스와 같이 소리나 화면이 잠깐 끊어져도 문제되지 않는 곳에 사용되었으나 근래에는 QoS(Quality of Service) 의 문제로 인해 멀티미디어 스트리밍에도 잘 쓰이지 않습니다.
• UDP 는 작고 가벼우며 빠르기 때문에 router 를 벗어나 지 않는 내부 네트웍용으로 많이 사용 됩니다.
아래는 Datagran에 관한 건데 참고로 읽어 보세요~(영어는 잘 되시죠^^;)
• The UDP protocol provides a mode of network communication whereby applications send packets of data, called datagrams, to one another.
• A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed.
결국 TCP는 신뢰할 수 있는 네트웍, 즉 데이터를 보내기 전에 연결을 설정하여 데이터를 보내고 또한 데이터가 잘 갔는지 확인하며 오류제어도 하면서 순서가 뒤틀리면 받는데서 정리도 하는 것임에 반해 UDP는 지나가는 강아지의 목에 주소만 써서 편지를 배달하는 것과 같이 전송을 보장 하지 않는 대신에 TCP보다는 빠른 프로토콜 입니다.
DatagramSocket
• DatagramPacket 객체를 전송하고 수신하는데 사용되며, 즉 DatagramPacket 을 사용하기 위해서는 DatagramSocket 을 생성해야 한다는 겁니다.
• DatagramSocket 객체 하나만 가지고도 여러 목적지로 패킷을 보낼 수 있으며 여러 발신지로 부터 패킷을 받을 수 있습니다. 어느 호스트로 부터 패킷을 받을지 정하는 방법은 없습니다.
• 대개 모든 DatagramSocket 은 하나의 Local port 에서 돌아 가며 이 port 에서 Socket 은 Host 로 들어오는 데이터를 기다리고 Network 으로 나가는 Datagram 에 헤더를 붙입니다.
• DatagramSocket 은 로컬호스트의 어떤 UDP Port 에서 패킷이 날아 오기만 기다리고 있으며 대개의 경우 서버 프로그램은 포트를 지정해 주며 클라이언트 프로그램의 경우 UDP 포트를 시스템에서 임의로 지정하게 하는 방식을 사용 합니다.
• TCP 처럼 Server 와 Client 별개의 소켓을 가지고 있지 않습니다.
• DatagramSocket 은 TCP 방식과는 달리 서버와 클라이언트가 동일하게 사용하며 , 먼저 서버측에서 소켓을 생성하여 대기하면 클라이언트가 소켓을 생성하여 데 이터를 전송을 하는 것입니다.
• UDP 서버와 TCP 서버는 같은 포트를 사용 할 수 있습니다.
다음은 생성자 입니다.
– DatagramSocket()
• Constructs a datagram socket and binds it to any available port on the local host machine.
– DatagramSocket(int port)
• Constructs a datagram socket and binds it to the specified port on the local host machine.
– DatagramSocket(int port, InetAddress laddr)
• Creates a datagram socket, bound to the specified local address.
• 보통 여러 개의 NIC(Network Interface Card) 가 꽃힌 컴퓨 터의 로컬 주소와 DatagramSocket 을 바인딩
DatagramPacket 클래스
• 하나의 데이터그램 패킷을 캡슐화
• 메시지 몸체와 목적지 주소로 구성
• DatagramPacket 클래스는 데이터그램을 사용할 수 있도록 기능을 제공해 주며 , 데이터그램 패킷은 비연결 패킷 전송 서비스 (connectionless packet delivery service) 를 구현하기 위해 사용 됩니다. 메시지는 패킷 내에 포함되어 있는 정보에 기반 하여 하나의 호스트에서 다른 호스트로 라우팅 됩니다.
• 한 호스트에서 다른 호스트로 전송된 여러 개의 패킷 (multiple packet) 은 서로 다르게 라우팅 될 것이며 , 원래의 순서와 관계없이 도착될 수 있습니다. 결국 DatagramPacket은 비연결 지향 패킷을 구현 했다고 보면 되겠네요...
생성자는 다음과 같습니다.
– DatagramPacket(byte[] buf, int length)
• Constructs a DatagramPacket for receiving packets of length length.
• buf 는 수신되는 UDP 패킷을 받아 낼 바이트 배열
– DatagramPacket(byte[] buf, int length, InetAddress address, int port)
• Constructs a datagram packet for sending packets of length length to the specified port number on the specified host.
다음은 데이터 송수신 순서 입니다. 잘보도록 하죠...
1. 서버는 클라이언트로부터 요청을 받고 그에 대해 응답을 하 기 위한 데이터그램 소켓을 생성하여 특정 포트에 연결 합니다 .
2 서버는 클라이언트로부터 오는 요청 내용을 저장할 입력 데이터그램 패킷을 생성한 뒤 클라이언트로부터 요청이 오기를 기다리며 대기 합니다.
3. 클라이언트 프로그램을 실행하면 서버에서와 마찬가지로 데이터그램 소켓을 하여 특정 포트에 연결 합니다.
4. 클라이언트 는 서버에 요청을 보내기 위한 출력 데이터그램 패킷을 생성한 뒤 서버에게 송신 합니다.
5. 서버는 클라이언트가 보낸 데이터그램 패킷을 받아 들이는데 여기서 서버는 이미 입력 데이터그램 패킷을 생성하고 대기하였는데 , 이 입력 데이터그램 패킷은 아무런 내용이 없는 빈 패킷으로서 이 패킷이 클라이언트가 보낸 데이터그램 패킷으로 대치 됩니다 . 따라서 서버 자신이 생성한 입력 데이터그램 패킷을 받는 것 자체가 곧 클라이언트가 보낸 데이터그램 패킷을 받는 것과 동일한 효과를 나타낸다 .
6. 클라이언트도 서버가 보낸 응답을 받기 위한 입력 데이터그 램 패킷을 생성하고 대기 합니다.
[ UDPDaytimeServer.java] -- 데이터그램서버 프로그램 입니다. 실행시 별다른 인자없이 실행하시면 됩니다.
import java.net.*;
import java.io.*;
import java.util.Date;
public class UDPDaytimeServer {
public static final int DAYTIME_PORT = 13;
public static void respond(DatagramSocket ds, DatagramPacket dp) {
DatagramPacket outgoing;
Date now = new Date();
String s = now.toString();
byte[] data = s.getBytes();
try {
outgoing = new DatagramPacket(data, data.length, dp.getAddress(), dp.getPort());
ds.send(outgoing);
}
catch (IOException e) {
System.err.println(e);
}
}
public static void main(String args[]) {
try {
DatagramSocket ds = new DatagramSocket(DAYTIME_PORT);
DatagramPacket incoming;
byte[] buffer = new byte[2048];
while(true) {
incoming = new DatagramPacket(buffer, buffer.length);
ds.receive(incoming);
respond(ds, incoming);
}
} catch(IOException e) {
System.out.println(e);
}
}
}
[ Daytime.java] -- 데이터그램 클라이언트 프로그램 입니다. 실행시 인자로 loclahost 정도 줘서 실행하시면 됩니다. java Daytime localhost
import java.io.*;
import java.net.*;
public class Daytime {
public static final int DAYTIME_PORT = 13;
public static final String getTime(String hostname) throws IOException {
InetAddress host;
DatagramSocket socket = new DatagramSocket();
byte[] dummyData = new byte[1];
byte[] timeData = new byte[256];
DatagramPacket sendPacket, receivePacket;
host = InetAddress.getByName(hostname);
sendPacket =
new DatagramPacket(dummyData, dummyData.length, host, DAYTIME_PORT);
receivePacket = new DatagramPacket(timeData, timeData.length);
socket.send(sendPacket);
socket.receive(receivePacket);
return
new String(receivePacket.getData(), 0, receivePacket.getLength());
}
public static void main(String[] args) {
String server = "localhost";
if(args.length == 1)
server = args[0];
else if(args.length > 1) {
System.err.println("Usage: Daytime [hostname]");
return;
}
try {
// Time should include newline, so we don't use println().
System.out.print(getTime(server));
System.out.flush();
} catch(IOException e) {
e.printStackTrace();
return;
}
}
}
[Daytime 실행 결과 입니다.]
출처 [강좌#9]UDP Datagram 다루기 |작성자 오라클러
http://blog.naver.com/julymorning4?Redirect=Log&logNo=100018686878