본문 바로가기

JAVA

Socket 을 활용한 네트워크 프로그래밍

1. 네트워크 프로그래밍


우리는 스마트폰이나, PC 등 인터넷을 사용해 왔다. 이처럼 사용자들이 다른 장비나 사용자들에게 데이터를 주고받는 작업을 네트워킹이라고 한다.

 

네트워킹은 TCP/IP 4계층이라는 계층이 존재한다.

네트워크의 공통 언어 TCP/IP

 

네트워크의 공통 언어 TCP/IP

1. TCP/IP 4계층 TCP/IP 에서는 네트워크를 통하여 통신하기 위한 기능을 계층화 하고, 복수의 프로토콜을 조합하여 실현하였다. 2. 네트워크 인터페이스층 네트워크 인터페이스층의 역할은 같은 네

dev-cool.tistory.com

  

자바에서 애플리케이션층에서 프로그래밍만 하면 트랜스포트층에서 처리는 자바에서 알아서 처리해준다.

 

트랜스포트층의 통신 방식으로 TCP방식과 UDP 방식이 존재하는데 차이점과 원리는 이전 포스팅에서 확인할 수 있다.

 

TCP (Transmission Control Protocol) 3-way handshake, 4-way handshake

 

TCP (Transmission Control Protocol) 3-way handshake, 4-way handshake

1. TCP란? TCP는 전송을 제어하는 프로토콜이라는 뜻으로 TCP/IP 4계층의 트랜스포트계층에 해당한다. 네트워크의 공통 언어 TCP/IP 네트워크의 공통 언어 TCP/IP 1. TCP/IP 4계층 TCP/IP 에서는 네트워크를

dev-cool.tistory.com

UDP (User Datagram Protocol)

 

UDP (User Datagram Protocol)

1. UDP란? 앞서 TCP의 특징에 대해서 살펴보았다. TCP는 신뢰성에 기반을 둔 트렌스포트계층 프로토콜 이라면 UDP는 빠른 데이터 전송을 목적으로 하는 프로토콜이다. TCP (Transmission Control Protocol) 3-way

dev-cool.tistory.com

 

2. Socket 클래스를 활용한 TCP 통신


 

자바에서 TCP 통신을 하기위해 Socket 클래스(Client)와 ServerSocket 클래스(Server)가 존재한다.

 

Client의 데이터를 받는 Server부분 부터 완성해보자.

 

public class SocketServer {
    public static void main(String[] args) {
        ServerSocket server = null;
        Socket client = null;

        try{
            //포트번호 9000번 으로 ServerSocket 객체 생성
            server = new ServerSocket(9000);

            while(true){
                System.out.println("Server Waiting");
                
                /*
                *  accept() 메소드를 호출하여 다른 원격 호출을 대기하는 상태로 만듬
                *  연결이 완료되면 Server 객체를 client 에 넘김
                * */
                client = server.accept();
                
                System.out.println("Server Accept");
                
                /*
                * 데이터를 받기위해 Socket 클래스의 getInputStream() 메소드를 통해 
                * InputStream 객체를 반환
                * */
                InputStream stream = client.getInputStream();

                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                String data = null;
                StringBuilder receiveData = new StringBuilder();
                while ((data=reader.readLine())!=null){
                    receiveData.append(data);
                }
                System.out.println("Receive Data : " + receiveData);

                reader.close();
                stream.close();
                client.close();

                if (receiveData != null && receiveData.toString().equals("EXIT")){
                    System.out.println("Stop Server");
                    break;
                }
                System.out.println("================");
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (server != null) {
                try {
                    server.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 

다음으로 데이터를 전송하는 Client부분을 완성해보자.

 

public class SocketClient {
    public static void main(String[] args) {
        SocketClient client = new SocketClient();
        for (int i = 0; i < 3; i++) {
            client.sendData("data " + (i + 1) + " send");
        }
        client.sendData("EXIT");
    }

    public void sendData(String data){
        Socket socket = null;
        try{
            System.out.println("Client Connect");
            
            /*
            * IP 는 127.0.0.1 으로 로컬호스트 
            * 즉, 같은 장비를 의미하며 포트번호는 9000으로 Socket 객체생성
            * */
            socket = new Socket("127.0.0.1",9000);
            
            System.out.println("Client connect status : " + socket.isConnected());
            Thread.sleep(1000);
            
            /*
            * 데이터를 서버에 전송하기 위해서 Socket 클래스의 getOutputStream()으로 
            * OutputStream 객체 반환
            * */
            OutputStream stream = socket.getOutputStream();
            
            BufferedOutputStream out = new BufferedOutputStream(stream);
            byte[] bytes = data.getBytes();
            out.write(bytes);
            System.out.println("Client Send Data" + data);
            out.close();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (socket != null){
                try{
                    socket.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

 

반드시 SocketServer 클래스를 먼저 실행한 후 새로운 터미널에서 SocketClient 클래스를 실행해야한다.

 

실행 후 결과를 살펴보면

SocketServer 초기 실행 화면

 

SocketClient 터미널 실행 결과

 

SocketClient 클래스 실행 후 SocketServer 터미널

 

처음 SocketServer 클래스를 실행하면 "Server Waiting"이라는 문구와 함께 accept() 메소드로 인하여 원격 호출을 대기하는 상태로 있는다.

 

포트가 제대로 열렸는지 확인하기 위해 cmd 창을 열어서 다음 명령어를 실행하면

netstat -ano

 

다음과 같이 TCP 프로토콜에 9000번 포트가 활성화 된것을 확인할 수 있다.

 

이제 SocketClient 클래스를 실행하면 메시지를 보내는 sendData() 메소드가 3번 호출되므로 메시지가 3번 전송되는것을 확인할 수 있다.

 

이때 SocketClient 클래스의 OutputStream으로 데이터를 송신하고, SocketServer클래스의 InputStream으로 데이터를 수신한다.

 

메시지를 전송한 후 SocketServer 터미널을 확인해보면 정상적으로 메시지를 전달 받은것을 알 수 있고, 마지막으로 "EXIT" 메시지를 전송하여 ServerSocket을 종료했다.

 

3. DatagramSocket 클래스를 활용한 UDP통신


 

자바에서 UDP 통신을 하기위해서 TCP 통신에서 사용하는 클래스가 아닌 다른 클래스를 사용한다. 

DatagramSocket 클래스이다. 

 

또한 TCP에서는 Stream객체를 통하여 데이터를 주고받았는데, UDP 통신은 Stream 대신 DatagramPacket이라는 클래스를 사용한다. 

 

UDP 통신의 Datagram의 개념에 대해서는 이전 포스팅을 참고하길 바랍니다.

 

먼저 Server 부분부터 완성해보면

public class DatagramServer {
    public static void main(String[] args) {
        DatagramSocket server = null;

        try{
            //포트번호 9000번 으로 DatagramSocket 객체 생성
            server = new DatagramSocket(9000);
            int bufferLength = 256;
            byte[] buffer = new byte[bufferLength];
            
            /*
            * 데이터를 받기위한 DatagramPacket 객체로 byte 배열과 크기를 지정하여 사용한다.
            * */
            DatagramPacket packet = new DatagramPacket(buffer,bufferLength);
            
            while (true){
                System.out.println("Server waiting");
                
                /*
                 *  receive() 메소드를 호출하여 데이터가 오기 전까지 대기
                 *  데이터가 넘어오면 packet 객체에 데이터를 담는다.
                 * */
                server.receive(packet);
                
                int dataLength = packet.getLength();
                System.out.println("Server received. Data length = " + dataLength);
                
                /*
                * String 생성자를 이용해서 byte 배열로 되어있는 데이터를 String 문자열로 변경한다.
                * */
                String data = new String(packet.getData(),0,dataLength);
                
                System.out.println("Received data : " + data);
                if (data.equals("EXIT")){
                    System.out.println("Stop Server");
                    break;
                }
                System.out.println("=====================");

            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (server != null){
                try{
                    server.close();
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

    }
}

다음으로 데이터를 전송하는 Client 부분을 완성해보면

public class DatagramClient {
    public static void main(String[] args) {
        DatagramClient dc = new DatagramClient();
        for (int i = 0; i < 3; i++) {
            dc.sendData("data " + (i + 1) +" send");
        }
        dc.sendData("EXIT");
    }

    public void sendData(String data){
        try{
            //아무런 매개변수 없이 DatagramSocket 클래스 생성
            DatagramSocket client = new DatagramSocket();
            
            /*
            * InetAddress 클래스를 사용하여 데이터를 받는 서버의 IP 주소를 설정한다.
            * */
            InetAddress address = InetAddress.getByName("127.0.0.1");
            
            byte[] buffer = data.getBytes();
            
            /*
             * 데이터를 보내기위한 DatagramPacket 객체로 서버의 주소와 포트번호를 매개변수로 넘겨주면
             * 데이터를 받는 객체가아닌 보내기위한 객체가 된다.
             * */
            DatagramPacket packet = new DatagramPacket(buffer,0,buffer.length,address,9000);
            
            /*
            * send() 메소드를 사용하여 데이터 전송
            * */
            client.send(packet);
            
            System.out.println("Client send Data : " + data);
            client.close();
            Thread.sleep(1000);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

TCP 통신과 마찬가지로 DatagramSocket 클래스를 실행한 후에 DatagramClient 클래스를 실행하여야 한다.

 

실행후 결과를 살펴보면

 

DatagramServer 초기 실행 화면

 

DatagramClient 터미널 실행 결과

 

DatagramClient 클래스 실행 후 DatagramServer 터미널

 

처음 DatagramServer 클래스를 실행해보면 "Server Waiting" 이라는 문구가 출력이 되고, receive() 메소드가 호출되면서 데이터가 넘어오는것을 기다리는 상태가 된다.

 

포트가 제대로 열렸는지 확인하기 위해서 cmd창을 열어 다음의 명령어를 입력하면

netstat -ano

다음과 같이 UDP 프로토콜에 9000번 포트가 활성화 된것을 확인할 수 있다.

 

이제 DatagramClient 클래스를 실행하면, 메시지를 전송하는 sendData() 메소드가 3번 실행되고 Server를 종료시키기 위해 "EXIT" 문구를 전송시킨다.

 

데이터를 전송하게 되면 보낸 메시지와 받은 메시지가 같고, Server가 정상적으로 종료되는것을 확인할 수 있다.

 

4. TCP 통신 vs UDP 통신


 

TCP 통신과 UDP 통신의 예로 먼저 Server단의 클래스를 먼저 실행 시키고 Client단의 클래스를 실행하였다.

 

TCP, UDP 에서 Client의 클래스를 먼저 실행시켜 보면서 두 통신방식의 차이점을 알아보자.

 

TCP 통신의 SocketClient 클래스를 먼저 실행했을 경우

 

 

TCP 통신의 경우 Client단의 클래스를 먼저 실행하였을 경우 ConnectionException이 발생하면서 반복문의 횟수만큼 에러메시지가 출력이 되는것을 확인할 수 있다.

 

TCP 통신의 특성상 3-way handshake 방식으로 연결하고 4-way handshake 방식으로 연결을 종료해야한다.

(자세한 내용은 이전 포스팅 참고)

TCP (Transmission Control Protocol) 3-way handshake, 4-way handshake

 

TCP (Transmission Control Protocol) 3-way handshake, 4-way handshake

1. TCP란? TCP는 전송을 제어하는 프로토콜이라는 뜻으로 TCP/IP 4계층의 트랜스포트계층에 해당한다. 네트워크의 공통 언어 TCP/IP 네트워크의 공통 언어 TCP/IP 1. TCP/IP 4계층 TCP/IP 에서는 네트워크를

dev-cool.tistory.com

 

즉, Server단이 준비되어 있지않다면 ConnectionException 에러를 발생하면서 정상적으로 통신할수가 없는 것이다.

 

UDP 통신의 DatagramClient 클래스를 먼저 실행했을 경우

 

반대로 UDP 통신의 경우 Client단의 클래스를 먼저 실행해도 아무런 이상없이 프로그램이 종료되는 것을 확인할 수 있다.

 

UDP 통신의 특성상 비연결형 통신방식이므로 Server단이 데이터를 받을 준비가 되어있지 않아도, Client단에서는 아무런 오류메시지 없이 정상적으로 프로그램을 수행한다.

(자세한 내용은 이전 포스팅 참고)

UDP (User Datagram Protocol)

 

UDP (User Datagram Protocol)

1. UDP란? 앞서 TCP의 특징에 대해서 살펴보았다. TCP는 신뢰성에 기반을 둔 트렌스포트계층 프로토콜 이라면 UDP는 빠른 데이터 전송을 목적으로 하는 프로토콜이다. TCP (Transmission Control Protocol) 3-way

dev-cool.tistory.com