MATT's

[JAVA] TCP 통신 (ServerSocket, Socket) 본문

Java

[JAVA] TCP 통신 (ServerSocket, Socket)

matt5659 2020. 2. 25. 23:12

1. 서버 통신 모듈

public class ServerMain {
	public static void main(String[] args) {
		ServerMain m = new ServerMain();
		m.tcpConnect();
	}
	
	/*
	 * TCP 통신 예시 (Server)
	 */
	private void tcpConnect() {
		try (ServerSocket serverSocket = new ServerSocket(8080)) {
			System.out.println("ServerSocekt connect...");
			// Connection 대기 상태 (.accept())
			Socket socket = serverSocket.accept();
			
			System.out.println("Connect success.");
			// Server -> Client로 전송할 데이터 write
			OutputStream os = socket.getOutputStream();
			String sendData = "send data test (server -> client)";
			os.write(sendData.getBytes());
			
			// Client -> Server로 전송한 데이터 수신
			InputStream is = socket.getInputStream();
			byte[] receiveData = new byte[100];
			is.read(receiveData);
			System.out.println(new String(receiveData));
			
			is.close();
			os.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
  • 1) Server에서는 ServerSocket을 통해 특정 port(8080)을 열어놓고 TCP 통신을 위한 connection 대기하게 된다.
  • 2) Client와 connection이 맺어지게 되면 "Connect success."라는 메세지를 출력하고, Client로 메세지를 전송한다.
  • 3) Client에서 메세지를 수신한 후 다시 Server쪽으로 메세지를 전송하여, Server에서는 메세지를 전달받는다.

 

2. 클라이언트 통신 모듈

public class ClientMain {
	public static void main(String[] args) {
		ClientMain m = new ClientMain();
		m.tcpConnect();
	}
	
	/**
	 * TCP 통신 예시 (Client)
	 */
	private void tcpConnect() {
		try (Socket socket = new Socket()) {
			// setSoTimeout : 연결 후 응답에 대한 timeout(3000) 지정
			socket.setSoTimeout(3000);
			// socket.connect의 인자로 있는 값(4000)은 연결 시의 timeout
			socket.connect(new InetSocketAddress("192.168.0.9", 8080), 4000);
			
			System.out.println("Connect Success.");
			
			// Server -> Client로 전송한 데이터 수신
			InputStream is = socket.getInputStream();
			byte[] receiveData = new byte[100];
			is.read(receiveData);
			System.out.println(new String(receiveData));
			
			// Client -> Server로 데이터 전송
			OutputStream os = socket.getOutputStream();
			String clientSendData = "send data test (client -> server)";
			os.write(clientSendData.getBytes());
			
			
			is.close();
			os.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

client 쪽의 코드 중 timeout이 2개가 걸려있는 것을 볼 수 있다.

socket.setSoTimeout(3000); 은 서버와의 연결 후 데이터를 요청했을 때, 응답에 대한 timeout을 설정하는 것이고,

socket.connect 메소드의 인자로 있는 값 (여기서는 4000을 뜻한다.)은 connection을 맺는데 걸리는 timeout을 설정하는 것이다.

 

"중요" 위 코드의 'receiveData' 변수를 보자.

위의 server, client 코드를 보면 'receiveData'는 100크기의 byte 배열로 지정이 되어있다.

server, client 두 쪽다 전달받을 데이터의 크기가 어느정도 될지 알 수 없다.

때문에 위의 코드는 테스트 코드라서 100으로 임의로 지정해둔 것이고, 현직에서는 저렇게 사용하지 않는다.

실제로 사용할 때는 "server에서는 몇 byte 만큼의 데이터를 보낼거니깐 client에서는 몇 byte 만큼의 데이터를 수신하면돼"

라고 약속을 하게 된다. (이것을 정의해놓은 문서를 '프로토콜 문서'라고 한다.)

 

일반적으로 String 데이터의 경우에는 길이가 짧을 수도 있고 길 수도 있는데, 어떻게 몇 byte만 보내겠다고 지정할 수 있지?

라고 생각할 수 있다.

맞다. 길이가 짧을 수도 있고 길 수도 있는 데이터들에 대해서는 몇 byte로 지정할 수 없다!

때문에 보통 '맨 앞부분 몇 byte는 길이 값을 보내줄게! 그니까 몇 byte만 먼저 받아서 길이 값을 계산하고 뒷부분은 그 길이만큼 받아!' 라고 약속해서 사용한다.

ex.

예를 들어 앞의 4byte는 길이 값을 보낸다고 약속이 되어 있다면,

...
// 보내는 쪽
String sendData = "send data test string";
int dataLength = sendData.length();

os.write(dataLength를 byte[4]로 변환한 값);
os.write(sendData.getBytes());
...
...
// 받는 쪽
byte[] lengthByte = new byte[4];
is.read(lengthByte);
int dataLength = (lengthByte를 int로 변환한 값)

byte[] data = new byte[dataLength];
is.read(data);
...

이런 식으로 사용하여 data를 받아올 수 있는 것이다.

 

 

'Java' 카테고리의 다른 글

[Java][테스트툴]JMeter  (0) 2022.05.17
POI 엑셀 생성 및 다운로드 (feat. RowHandler, ResultHandler)  (0) 2020.06.22