java.net
패키지를 통해 소켓 프로그래밍을 지원한다.데이터를 전송하기 전에 먼저 상대편과 연결을 한 후에 데이터를 전송하며 잘 전송되었는지 확인하고 전송에 실패했다면 해당 데이터를 재전송하기 때문에 신뢰 있는 데이터의 전송이 요구되는 통신에 적합하다. 예를 들어 파일을 주고받는데 적합하다.
상대편과 연결하지 않고 데이터를 전송하며, 데이터를 전송하지만 데이터가 바르게 수신되었는지 확인하지 않기 때문에 데이터가 전송되었는지 확인할 길이 없다. 또한 데이터를 보낸 순서대로 수신한다는 보장이 없다.
대신 이와같은 확인 과정이 필요하지 않아 TCP에 비해 전송 속도가 빠르며, 게임이나 동영상의 데이터 전송과 같이 일부 데이터가 손실되어 끊기더라도 빠른 전송이 필요할 때 적합하다. 이때 전송 순서가 바뀌어 늦게 도착한 데이터는 무시하면 된다.
서버 프로그램과 클라이언트 프로그램간의 통신 과정
- 서버 프로그램에서는 서버소켓을 사용해서 서버 컴퓨터의 특정 포트에서 클라이언트의 연결요청을 처리할 준비를 한다.
- 클라이언트 프로그램은 접속할 서버의 IP주소와 포트 정보를 가지고 소켓을 생성해서 서버에 연결을 요청한다.
- 서버소켓은 클라이언트의 연결요청을 받으면 서버에 새로운 소켓을 생성해서 클라이언트의 소켓과 연결되도록 한다.
- 이제 클라이언트의 소켓과 새로 생성된 서버의 소켓은 서버소켓과 관계없이 일대일 통신을 한다.
두 서버소켓이 서로 다른 프로토콜을 사용하는 경우에는 같은 포트를 사용할 수 있다. 포트는 같아도 클라이언트 프로그램이 사용하는 프로토콜로 어떤 서버소켓과 연결되어야 하는지 구별할 수 있기 때문이다. 그래돼 가능하면 하나의 포트는 하나의 서버소켓만 사용하도록 하는 것이 바람직하다.
Socket
InputStream
과 OutputStream
을 가지고 있다. ServerSocekt
package _ch16;
import java.net.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.io.*;
public class TcpIpServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
// 서버소켓을 생성하여 7777번 포트와 결합(bind) 시킨다.
serverSocket = new ServerSocket(7777);
System.out.println(getTime() + "서버가 준비되었습니다.");
} catch(IOException e) {
e.printStackTrace();
}
while(true) {
try {
System.out.println(getTime() +"연결 요청을 기다립니다.");
// 서버 소켓은 클라이언트의 연결요청이 올 때까지 실행을 멈추고 계속 기다린다.
// 클라이언트의 연결 요청이 오면 클라이언트 소켓과 통신할 새로운 소켓을 생성한다.
Socket socket = serverSocket.accept();
System.out.println(getTime() + socket.getInetAddress() +
"로부터 연결요청이 들어왔습니다.");
// 소켓의 출력 스트림을 얻는다.
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
// 원격 소켓(remote socket)에 데이터를 보낸다.
dos.writeUTF("[Notice] Test Message1 from Server");
System.out.println(getTime() + "데이터를 전송했습니다.");
// 스트림과 소켓을 닫아준다.
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
} // while
} // main
// 현재 시간을 문자열로 반환하는 함수
static String getTime() {
SimpleDateFormat f = new SimpleDateFormat("[hh:mm:ss]");
return f.format(new Date());
}
} // class
"[Notice] Test Message1 from Server"
라는 데이터를 원격소켓에 전송하로 연결을 종료한다.while(true) {
try {
...
Socket socket = serverSocket.accept();
...
Ctrl + C
를 눌러 강제종료시켜야 한다.[11:02:01]서버가 준비되었습니다.
[11:02:01]연결 요청을 기다립니다.
[11:02:04]/127.0.0.1로부터 연결요청이 들어왔습니다.
[11:02:04]데이터를 전송했습니다.
[11:02:04]연결 요청을 기다립니다.
package _ch16;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;
import java.net.Socket;
public class TcpIpClient {
public static void main(String[] args) {
try {
String serverIp = "127.0.0.1";
System.out.println("서버에 연결중입니다. 서버IP :" + serverIp);
// 소켓을 생성하여 연결을 요청한다.
Socket socket = new Socket(serverIp, 7777);
// 소켓의 입려스트림을 얻는다.
InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
// 소켓으로 부터 받은 데이터를 출력한다.
System.out.println("서버로부터 받은 메시지 :" + dis.readUTF());
System.out.println("연결을 종료합니다.");
// 스트림과 소켓을 닫는다.
dis.close();
socket.close();
System.out.println("연결이 종료되었습니다.");
} catch (ConnectException ce) {
ce.printStackTrace();
} catch (IOException ie) {
ie.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} // main
}
String serverIp = "127.0.0.1";
Socket socket = new Socket(serverIp, 7777);
ConnectException
이 발생한다.InputStream in = socket.getInputStream();
DataInputStream dis = new DataInputStream(in);
// 소켓으로부터 받은 데이터를 출력한다.
System.out.println("서버로부터 받은 메시지 :" + dis.readUTF());
dis.close();
socket.close();
서버에 연결중입니다. 서버IP :127.0.0.1
서버로부터 받은 메시지 :[Notice] Test Message1 from Server
연결을 종료합니다.
연결이 종료되었습니다.
서버의 IP는 192.168.10.100
, 클라이언트 IP는 192.168.10.101
이라고 가정하자.
TcpIpServer.java
)를 실행한다.serverSocket = new ServerSocket(7777); // TcpIpServer.java
Socket socket = serverSocket.accept(); // TcpIpServer.java
Socket socket = new Socket("192.168.10.100", 7777)
Socket socket = serverSocket.accept();
package _ch16;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TcpIpServer2 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
// 서버소켓을 생성하여 7777번 포트와 결합(bind)시킨다.
serverSocket = new ServerSocket(7777);
System.out.println(getTime() + "서버가 준비되었습니다.");
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
// 서버소켓
System.out.println(getTime() + "연결요청을 기다립니다.");
Socket socket = serverSocket.accept();
System.out.println(getTime() + socket.getInetAddress()
+ "로부터 연결요청이 들어왔습니다.");
System.out.println("getPort() :" + socket.getPort());
System.out.println("getLocalPort() :" + socket.getLocalPort());
// 소켓의 출력 스트림을 얻는다.
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
// 원격 소켓(remote socket)에 데이터를 보낸다.
dos.writeUTF("[Notice] Test Message1 from Server.");
System.out.println(getTime() + "데이터를 전송했습니다.");
// 스트림과 소켓을 닫아준다.
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
} // while
} // main
// 현재 시간을 문자열로 반환하는 함수
static String getTime() {
SimpleDateFormat f = new SimpleDateFormat("[hh:mm:ss]");
return f.format(new Date());
}
}
getPort()
와 getLocalPort()
를 사용해서 TCP/IP 통신에서 소켓이 사용하고 있는 포트를 알아낼 수 있다.getPort()
가 반환하는 값은 상대편 소켓(원격 소켓)이 사용하는 포트이다.getLocalPort()
가 반환하는 값은 소켓 자신이 사용하는 포트이다.[12:07:17]서버가 준비되었습니다.
[12:07:17]연결요청을 기다립니다.
[12:07:21]/127.0.0.1로부터 연결요청이 들어왔습니다.
getPort() :2839
getLocalPort() :7777
[12:07:21]데이터를 전송했습니다.
[12:07:21]연결요청을 기다립니다.
package _ch16;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TcpIpServer3 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
// 서버소켓을 생성하여 7777번 포트와 결합(bind)시킨다.
serverSocket = new ServerSocket(7777);
System.out.println(getTime() + "서버가 준비되었습니다.");
} catch (IOException e) {
e.printStackTrace();
}
while(true) {
try {
System.out.println(getTime() + "연결요청을 기다립니다.");
// 요청 대기 시간을 5초로 설정한다.
// 5초동안 접속요청이 없으면 SocketTimeoutException이 발생한다.
serverSocket.setSoTimeout(5 * 1000);
Socket socket = serverSocket.accept();
System.out.println(getTime() + socket.getInetAddress()
+ "로부터 연결요청이 들어왔습니다.");
// 소켓의 출력 스크림을 받는다.
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
// 원격 소켓(remote socket)에 데이터를 보낸다.
dos.writeUTF("[Notice] Test Message1 from Server.");
System.out.println(getTime() + "데이터를 전송했습니다.");
// 스트림과 소켓을 닫아준다.
dos.close();
socket.close();
} catch (SocketTimeoutException e) {
System.out.println("지정된 시간동안 접속요청이 없어서 서버를 종료합니다.");
System.exit(0);
} catch(IOException e) {
e.printStackTrace();
}
}
}
static String getTime() { // 현재 시간을 문자열로 반환하는 함수
SimpleDateFormat f = new SimpleDateFormat("[hh:mm:ss]");
return f.format(new Date());
}
}
setSoTimeout(int timeout)
을 사용해 서버소켓의 대기시간을 지정할 수 있다.[12:19:31]서버가 준비되었습니다.
[12:19:31]연결요청을 기다립니다.
지정된 시간동안 접속요청이 없어서 서버를 종료합니다.
package _ch16;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TcpIpServer4 implements Runnable {
ServerSocket serverSocket;
Thread[] threadArr;
public static void main(String[] args) {
// 5개의 쓰레드를 생성하는 서버를 생성한다.
TcpIpServer4 server = new TcpIpServer4(5);
server.start();
} // main
public TcpIpServer4(int num) {
try {
// 서버소켓을 생성하여 7777번 포트와 결합(bind)시킨다.
serverSocket = new ServerSocket(7777);
System.out.println(getTime() + "서버가 준비되었습니다.");
threadArr = new Thread[num];
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() {
for (int i = 0; i < threadArr.length; i++) {
threadArr[i] = new Thread(this);
threadArr[i].start();
}
}
public void run() {
while(true) {
try {
System.out.println(getTime() + "가 연결요청을 기다립니다.");
Socket socket = serverSocket.accept();
System.out.println(getTime() + socket.getInetAddress()
+ "로부터 연결요청이 들어왔습니다.");
// 소켓의 출력스트림을 얻는다.
OutputStream out = socket.getOutputStream();
DataOutputStream dos = new DataOutputStream(out);
// 원격 소켓(remote socket)에 데이터를 보낸다.
dos.writeUTF("[Notice] Test Message1 from Server.");
System.out.println(getTime() + " 데이터를 전송했습니다.");
// 스트림과 소켓을 닫아준다.
dos.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
static String getTime() { // 현재 시간을 문자열로 반환하는 함수
String name = Thread.currentThread().getName();
SimpleDateFormat f = new SimpleDateFormat("[hh:mm:ss]");
return f.format(new Date()) + name;
}
}
[12:31:12]main서버가 준비되었습니다.
[12:31:12]Thread-4가 연결요청을 기다립니다.
[12:31:12]Thread-2가 연결요청을 기다립니다.
[12:31:12]Thread-1가 연결요청을 기다립니다.
[12:31:12]Thread-3가 연결요청을 기다립니다.
[12:31:12]Thread-0가 연결요청을 기다립니다.
[12:31:16]Thread-4/127.0.0.1로부터 연결요청이 들어왔습니다.
[12:31:16]Thread-4 데이터를 전송했습니다.
[12:31:16]Thread-4가 연결요청을 기다립니다.
[12:31:18]Thread-2/127.0.0.1로부터 연결요청이 들어왔습니다.
[12:31:18]Thread-2 데이터를 전송했습니다.
[12:31:18]Thread-2가 연결요청을 기다립니다.
[12:31:19]Thread-0/127.0.0.1로부터 연결요청이 들어왔습니다.
[12:31:19]Thread-0 데이터를 전송했습니다.
[12:31:19]Thread-0가 연결요청을 기다립니다.
[12:31:20]Thread-1/127.0.0.1로부터 연결요청이 들어왔습니다.
[12:31:20]Thread-1 데이터를 전송했습니다.
[12:31:20]Thread-1가 연결요청을 기다립니다.
[12:31:21]Thread-3/127.0.0.1로부터 연결요청이 들어왔습니다.
[12:31:21]Thread-3 데이터를 전송했습니다.
[12:31:21]Thread-3가 연결요청을 기다립니다.
[12:31:22]Thread-4/127.0.0.1로부터 연결요청이 들어왔습니다.
[12:31:22]Thread-4 데이터를 전송했습니다.
[12:31:22]Thread-4가 연결요청을 기다립니다.
package _ch16;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class TcpIpServer5 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
// 서버소켓을 생성하여 7777번 포트와 결합(bind)시킨다.
serverSocket = new ServerSocket(7777);
System.out.println("서버가 준비되었습니다.");
socket = serverSocket.accept();
Sender sender = new Sender(socket);
Receiver receiver = new Receiver(socket);
sender.start();
receiver.start();
} catch (Exception e) {
e.printStackTrace();
}
} // main()
} // class
class Sender extends Thread {
Socket socket;
DataOutputStream out;
String name;
Sender(Socket socket) {
this.socket = socket;
try {
out = new DataOutputStream(socket.getOutputStream());
name = "[" + socket.getInetAddress() + " : " + socket.getPort() + "]";
} catch (Exception e) {}
}
public void run() {
Scanner scanner = new Scanner(System.in);
while(out != null) {
try {
out.writeUTF(name + scanner.nextLine());
} catch (IOException e) {}
}
} // run()
}
class Receiver extends Thread {
Socket socket;
DataInputStream in;
Receiver(Socket socket) {
this.socket = socket;
try {
in = new DataInputStream(socket.getInputStream());
} catch (IOException e) {}
}
public void run() {
while(in != null) {
try {
System.out.println(in.readUTF());
} catch(IOException e) {}
}
} // run()
}
TcpIpServer5
)과 클라이언트 프로그램(TcpIpClient5
)의 화면에 입력한 데이터가 상대방의 화면에 출력되므로 1:1 채팅이 가능하다.package _ch16;
import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;
public class TcpIpClient5 {
public static void main(String[] args) {
try {
String serverIp = "127.0.0.1";
// 소켓을 생성하여 연결을 요청한다.
Socket socket = new Socket(serverIp,7777);
System.out.println("서버에 연결되었습니다.");
Sender sender = new Sender(socket);
Receiver receiver = new Receiver(socket);
sender.start();
receiver.start();
} catch(ConnectException ce) {
ce.printStackTrace();
} catch(IOException ie) {
ie.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
} // main
} // class
package _ch16;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
public class TcpIpMultichatServer {
HashMap clients;
TcpIpMultichatServer() {
clients = new HashMap();
Collections.synchronizedMap(clients);
}
public void start() {
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket(7777);
System.out.println("서버가 시작되었습니다.");
while(true) {
socket = serverSocket.accept();
System.out.println("[" + socket.getInetAddress()
+" : " + socket.getPort() + "] 에서 접속하셨습니다.");
ServerReceiver thread = new ServerReceiver(socket);
thread.start();
}
} catch(Exception e) {
e.printStackTrace();
}
}
void sendToAll(String msg) {
Iterator it = clients.keySet().iterator();
while(it.hasNext()) {
try {
DataOutputStream out = (DataOutputStream) clients.get(it.next());
out.writeUTF(msg);
} catch(IOException e) {}
} //while
}// sendToAll
public static void main(String args[]) {
new TcpIpMultichatServer().start();
}
class ServerReceiver extends Thread {
Socket socket;
DataInputStream in;
DataOutputStream out;
ServerReceiver(Socket socket) {
this.socket = socket;
try {
in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
} catch(IOException e) {}
}
public void run() {
String name = "";
try {
name = in.readUTF();
sendToAll("#" + name + "님이 들어오셨습니다.");
clients.put(name, out);
System.out.println("현재 서버접속자 수는 " + clients.size() + "입니다.");
while(in != null) {
sendToAll(in.readUTF());
}
} catch(IOException e) {
// ignore
} finally {
sendToAll("#" + name + "님이 나가셨습니다.");
clients.remove(name);
System.out.println("[" + socket.getInetAddress()
+ " : " + socket.getPort() + "] 에서 접속을 종료하셨습니다.");
System.out.println("현재 서버 접속자수는 " + clients.size() + "입니다.");
} // try
} // run
} // ReceiverThread
} // class
서버가 시작되었습니다.
[/127.0.0.1 : 53967] 에서 접속하셨습니다.
현재 서버접속자 수는 1입니다.
[/127.0.0.1 : 53976] 에서 접속하셨습니다.
현재 서버접속자 수는 2입니다.
[/127.0.0.1 : 53988] 에서 접속하셨습니다.
현재 서버접속자 수는 3입니다.
[/127.0.0.1 : 53967] 에서 접속을 종료하셨습니다.
현재 서버 접속자수는 2입니다.
[/127.0.0.1 : 53988] 에서 접속을 종료하셨습니다.
현재 서버 접속자수는 1입니다.
[/127.0.0.1 : 53976] 에서 접속을 종료하셨습니다.
현재 서버 접속자수는 0입니다.
package _ch16;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ConnectException;
import java.net.Socket;
import java.util.Scanner;
public class TcpIpMultichatClient {
public static void main(String[] args) {
if(args.length != 1) {
System.out.println("USAGE: java TcpIpMultichatClient 대화명");
System.exit(0);
}
try {
String serverIp = "127.0.0.1";
// 소켓을 생성하여 연결을 요청한다.
Socket socket = new Socket(serverIp, 7777);
System.out.println("서버에 연결되었습니다.");
Thread sender = new Thread(new ClientSender(socket, args[0]));
Thread receiver = new Thread(new ClientReceiver(socket));
sender.start();
receiver.start();
} catch(ConnectException ce) {
ce.printStackTrace();
} catch(Exception e) {
e.printStackTrace();
}
} // main
static class ClientSender extends Thread {
Socket socket;
DataOutputStream out;
String name;
ClientSender(Socket socket, String name) {
this.socket = socket;
try {
out = new DataOutputStream(socket.getOutputStream());
this.name = name;
} catch (Exception e) {
}
}
public void run() {
Scanner scanner = new Scanner(System.in);
try {
if (out != null) {
out.writeUTF(name);
}
while (out != null) {
out.writeUTF("[" + name + "]" + scanner.nextLine());
}
} catch (IOException e) {
}
} // run()
} // ClientSender
static class ClientReceiver extends Thread {
Socket socket;
DataInputStream in;
ClientReceiver(Socket socket) {
this.socket = socket;
try {
in = new DataInputStream(socket.getInputStream());
} catch (IOException e) {
}
}
public void run() {
while (in != null) {
try {
System.out.println(in.readUTF());
} catch (IOException e) {
}
}
} // run
} // ClientReceiver
} // class
C:\jdk1.8\work>java TcpIpMultichatClient aaa
서버에 연결되었습니다.
#bbb님이 들어오셨습니다.
#ccc님이 들어오셨습니다.
안녕하세요!
[aaa]안녕하세요!
[ccc]반갑습니다~
[bbb]만나서 반가워요~~
저는 가보겠습니다!
[aaa]저는 가보겠습니다!
C:\jdk1.8\work>java TcpIpMultichatClient bbb
서버에 연결되었습니다.
#ccc님이 들어오셨습니다.
[aaa]안녕하세요!
[ccc]반갑습니다~
만나서 반가워요~~
[bbb]만나서 반가워요~~
[aaa]저는 가보겠습니다!
#aaa님이 나가셨습니다.
#ccc님이 나가셨습니다.
C:\jdk1.8\work>java TcpIpMultichatClient ccc
서버에 연결되었습니다.
[aaa]안녕하세요!
반갑습니다~
[ccc]반갑습니다~
[bbb]만나서 반가워요~~
[aaa]저는 가보겠습니다!
#aaa님이 나가셨습니다.
서버 프로그램(TcpIpMultichatServer.java
)을 보면 서버에 접속한 클라이언트 (TcpIpMultichatClient.java
)를 HashMap에 저장해서 관리하고 있다.
TcpIpMultichatServer() {
clients = new HashMap();
Collections.synchronizedMap(clients); // 동기화 처리
멀티채팅서버의 ServerReceiver
쓰레드는 클라이언트가 추가될 때마다 생성되며 클라이언트의 입력을 서버에 접속된 모든 클라이언트에게 전송하는 일을 한다.
void sendToAll(String msg) {
Iterator it = clients.keySet().iterator(); //**
while(it.hasNext()) {
try {
DataOutputStream out = (DataOutputStream) clients.get(it.next));
out.writeUTF(msg);
} catch(IOException e) {}
} // while
} // sendToAll
run()
public void run() {
...
try {
...
clients.put(name, out);
System.out.println("현재 서버 접속자 수는" + clients.size() + "입니다.);
while(in != null) {
sendToAll(in.readUTf));
}
} catch(IOException e ) {
// ignore
} finally {
sendToAll("#" + name + "님이 나가셨습니다.");
clients.remove(name);
...
} // try
} // run
DatagramSocket
과 DatagramPacket
을 사용한다.ServerSocket
이 필요하지 않다.DatagramSocket
이며 데이터를 DatagramPacket
에 담아서 전송한다.DatagramPacket
DatagramPacket
을 수신할 호스트의 정보(호스트의 주소와 포트)가 저장되어 있다. 소포(packet)에 수신할 상대편의 주소를 적어서 보내는 것과 같다고이해하면 된다.DatagramPacket
을 전송하면 DatagramPacket에 지정된 주소(호스트의 포트)의 DatagramSocket에 도착한다.package _ch16;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class UdpClient {
public void start() throws IOException, UnknownHostException {
DatagramSocket datagramSocket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName("127.0.0.1");
// 데이터가 저장될 공간으로 byte배열을 생성한다.
byte[] msg = new byte[100];
DatagramPacket outPacket = new DatagramPacket(msg, 1, serverAddress, 7777);
DatagramPacket inPacket = new DatagramPacket(msg, msg.length);
datagramSocket.send(outPacket); // DatagramPacket을 전송한다.
datagramSocket.receive(inPacket); // DatagramPacket을 수신한다.
System.out.println("current server time :" + new String(inPacket.getData()));
datagramSocket.close();
} // start
public static void main(String args[]) {
try {
new UdpClient().start();
} catch(Exception e) {
e.printStackTrace();
}
} // main
}
current server time :[02:02:01]
package _ch16;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
public class UdpServer {
public void start() throws IOException {
// 포트 7777번을 사용하는 소켓을 생성한다.
DatagramSocket socket = new DatagramSocket(7777);
DatagramPacket inPacket, outPacket;
byte[] inMsg = new byte[10];
byte[] outMsg;
while(true) {
// 데이터를 수신하기 위한 패킷을 생성한다.
inPacket = new DatagramPacket(inMsg, inMsg.length);
// 패킷을 통해 데잍를 수신(receive)한다.
socket.receive(inPacket);
// 수신한 패킷으로부터 client의 IP주소와 Port를 얻는다.
InetAddress address = inPacket.getAddress();
int port = inPacket.getPort();
// 서버의 현재 시간을 시분초 형태([hh:mm:ss])로 반환한다.
SimpleDateFormat sdf = new SimpleDateFormat("[hh:mm:ss]");
String time = sdf.format(new Date());
outMsg = time.getBytes(); // time읠 byte배열로 변환한다.
// 패킷을 생성해서 client에게 전송(send)한다.
outPacket = new DatagramPacket(outMsg, outMsg.length, address, port);
socket.send(outPacket);
}
} // start()
public static void main(String[] args) {
try {
// UDP서버를 실행시킨다.
new UdpServer().start();
} catch(IOException e) {
e.printStackTrace();
}
} // main
}
UdpClient 실행 전 UdpServer를 먼저 실행해야 한다.