Java/Network

[Java] 네트워크(Networking) : TCP 통신

아, 그래요? 2022. 1. 4. 16:35
들어가기 앞서...

본 포스팅은 TCP 통신을 '자바로 어떻게 구현'하는지에 대한 이야기입니다. TCP 통신 자체에 대한 내용은 이후 [컴퓨터공학] 카테고리에 작성할 예정입니다 :)

 

TCP 서버의 역할

TCP 서버의 역할은 두가지이다. 첫째는 클라이언트의 연결 요청을 수락하는 것이고, 둘째는 클라이언트와 통신하는 것이다. 이때 연결 요청을 수락하는 역할을 하는 것이 ServerSocket 객체이고, 통신을 하는 역할이 Socket 객체이다. 

 

이때 Client의 socket 객체는 connect() 메서드를 통해 연결을 요청하고 ServerSocket은 accept() 메서드를 통해 연결을 수락한다. 또한 연결 요청시에는 반드시 서버의 ip주소와 포트번호가 있어야 한다.

 

ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetAddress("localhost", 5001));
try {
	Socket socket = serverSocket.accept();
} catch (Exception e) {}

위 코드는 ServerSocket 객체를 생성한 후, 클라이언트의 요청을 수락하는 코드이다. ServerSocket을 생성시 생성후, bind() 메서드를 통해 IP주소와 포트를 바인딩한다. 그후 accept() 메서드를 통해 클라이언트의 연결 요청을 수락한다. 이때, 클라이언트에게 연결 요청이 올때까지 코드는 정지해 있는다.

 

Socket socket = new Socket();
socket.connect(new InetAddress("localhost", 5001));

위 코드는 클라이언트가 서버에게 연결을 요청하는 코드이다. connect 메서드에 인자로 IP주소와 포트번호를 넣어주어 해당 서버에 연결을 요청한다.

 

클라이언트와 서버의 통신

클라이언트와 서버는 자바가 제공하는 Socket 객체를 이용해 통신한다. 통신시에는 IO기반의 입출력 스트림을 사용한다. Socket은 내부의 getInputStream()getOutputStream() 메서드를 내장하고 있어 해당 메서드를 통해 입력/출력 스트림을 얻어 데이터를 주고 받는다.

byte[] byteArr = new byte[100];
InputStream is = socket.getInputStream();
int readByteCnt = is.read(byteArr);

String data = new String(byteArr, 0, readByteCnt, "UTF-8");

위 코드는 서버에서 데이터를 받는 코드이다. socket으로 부터 입력 스트림 객체를 받는다. 그리고 입력 스트림 객체의 read() 메서드를 통해 받은 data를 byteArr에 저장한후 문자열 형태로 다시 변형해 data에 저장한다.

 

// data : 보낼 데이터
byte[] byteArr = data.getBytes("UTF-8");
OutputStream os = socket.getOutputStream();
os.write(byteArr);
os.flush();

다음 코드는 다른 서버로 데이터를 보내는 코드이다. 보낼 데이터(data)를 바이트 배열로 변형하여 byteArr에 저장한다. 그후 getOutputStream() 메서드를 통해 출력 스트림을 얻어 write() 메서드를 통해 데이터를 전송한다.

 

Socket과 ServerSocket의 종료

Socket과 ServerSocket 모두 close() 메서드를 통해 연결을 종료할 수 있다. 또한 isClosed() 메서드를 통해 현재 객체가 닫혀있는지 여부를 알 수 있다. close() 메서드의 경우, IOException을 발생시킬 수도 있기 때문에 예외처리가 필수적이다.

try {
	if (socket.isClosed()) { socket.close(); }
} catch (Exception e) {}