간단한 프로그램 작성해보자
→ 클라이언트가 “Hello”를 보내면 서버가 “World!” 를 붙여서 응답
// 클라이언트 코드
public class ClientV1 {
private static final int PORT = 12345;
public static void main(String[] args) throws java.io.IOException {
// 클라이언트 시작
Socket socket = new Socket("localhost", PORT);
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
// 서버에 문자 보내기
output.writeUTF("Hello");
// 서버로부터 문자 받기
String received = input.readUTF();
// 자원 정리
input.close();
output.close();
socket.close();
}
}
// 서버코드
public class ServerV1 {
private static final int PORT = 12345;
public static void main(String[] args) throws IOException {
// 서버는 특정 포트를 열어두어야 클라이언트의 요청을 받을 수 있다.
ServerSocket serverSocket = new ServerSocket(PORT);
// 서버 소켓은 클라이언트와 서버의 TCP 연결만을 지원하는 특별한 소켓이다.
// 실제 클라이언트와 정보를 주고 받으려면 Socket 객체가 필요하다.
// accept 메서드를 호출하면 TCP 연결 정보를 기반으로 Socket 객체를 만들어서 반환한다.
// TCP 연결 정보는 OS 단에 backlog queue에 저장되었다가..
// socket을 생성해서 반환하는 순간 제거한다.
Socket socket = serverSocket.accept();
// 모든 데이터를 byte를 변환하는 과정이 번거로워서 보조 스트림을 사용한다.
DataInputStream input = new DataInputStream(socket.getInputStream());
DataOutputStream output = new DataOutputStream(socket.getOutputStream());
// 클라이언트로부터 문자 받기
String received = input.readUTF();
// 클라이언트에게 문자 보내기
output.writeUTF(received + " World!");
// 자원 정리
input.close();
output.close();
socket.close();
serverSocket.close();
}
}
클라이언트와 서버는 socket을 통해서 통신할 수 있고, 이때도 inputStream, outputStream을 사용한다.
TCP/IP 통신에서는 통신할 대상 서버를 찾을 때 호스트 이름이 아니라 IP 주소가 필요하다.
호스트 이름으로 IP를 어떻게 찾는지 살펴보자.
public class InetAddressMain {
public static void main(String[] args) throws UnknownHostException {
InetAddress localhosts = InetAddress.getByName("localhost");
System.out.println(localhosts); // localhost/127.0.0.1
InetAddress google = InetAddress.getByName("google.com");
System.out.println("google = " + google); // google = google.com/142.250.198.14
}
}
자바는 InetAddress 클래스를 이용해 호스트 이름으로 대상 IP를 찾을 수 있다.