소켓 네트워크 프로그래밍

진경천·2024년 10월 1일

Java

목록 보기
9/9

TCP/IP 모델

하나의 프로토콜이 아닌 TCP와 IP를 합쳐서 부르는 말이다.

TCP/IP를 사용한다는 것은 IP 주소 체계를 따르고 IP Routing을 통해 목적지에 도달하며, TCP의 특성을 활용해 송시자와 수신자의 논리적 연결을 생성 및 신뢰성을 유지할 수 있도록 하겠다는 것.

네트워크 통신이 일어나는 과정을 4단계로 구분

4 응용 계층
3 전송 계층 ------------ TCP, UDP가 속함
2 인터넷 계층
1 네트워크 엑세스 계층

TCP

통신하고자 하는 양쪽 단말이 통신할 준비가 되었는지, 데이터가 제대로 전송되었는지, 데이터의 변질 여부 등을 점검한다.

특징

  • 연결형 방식
  • 흐름 및 혼잡 제어
  • 신뢰성 보장
  • UDP보다 느림
  • full-duplex, point to point 방식
  • 이메일 및 파일 전송, 웹페이 로딩에 사용

3-way handshake

TCP 연결을 초기화할 때 사용되는 절차로, 신뢰성 있는 연결을 맺어준다.

  1. 클라이언트가 서버에 접속을 요청하는 SYN 패킷을 보내고 SYN/ACK 응답을 기다린다.
  2. 서버는 SYN요청을 받고 요청을 수락한다는 ACK와 SYN플래그가 설정된 패킷을 발송하고 클라이언트의 ACK 응답을 기다린다.
  3. 클라이언트는 서버에게 ACK를 보내고 연결이 이루어진다.

4-way handshake

세션을 종료하기 위한 절차이다.

  1. 클라이언트가 연결을 종료하겠다는 FIN플래그를 전송한다.
  2. 서버는 ACK를 보내고 자신의 통신이 끝날때까지 기다린다.
  3. 서버가 종료될 준비가 끝나면 연결이 종료되었다고 클라이언트에게 FIN플래그를 전송한다.
  4. 클라이언트가 서버의 종료를 승인한다는 ACK를 서버에 보낸다.

예제

Server

package ch4.socket.server;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class TCPServer {
    static int portNum = 62289; // 서버 포트 번호
    public static void main(String[] args) throws IOException {
        ServerSocket welcomeSocket = new ServerSocket(portNum); // 6789의 포트번호를 갖는 서버의 생성

        while (true) {
            System.out.println("서버가 " + portNum + " 포트에서 클라이언트의 연결을 기다립니다...");
            Socket connectionSocket = welcomeSocket.accept(); // 서버가 요청을 받을 준비가 됨
            System.out.println("클라이언트와 연결되었습니다.");

            BufferedReader inFromClient = new BufferedReader
                    (new InputStreamReader(connectionSocket.getInputStream())); // 유저한테서 읽어들일 input
            DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream()); // 유저한테 보낼 output

            String clientSentence = inFromClient.readLine(); // 유저한테 받은 문자열 저장
            System.out.println("클라이언트로부터 받은 메시지: " + clientSentence);

            String capitalizedSentence = clientSentence.toUpperCase() + "11" + '\n'; // 유저한테 받은 문자열 변환
            //outToClient.writeBytes(capitalizedSentence); // 한글 깨짐
            outToClient.write(capitalizedSentence.getBytes()); // 수정된 문자열 유저한테 write
        }
    }
}

Client

import ch4.socket.server.TCPServer;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

public class TCPClient {
    public static void main(String[] args) throws IOException {
        String sentence;
        String modifiedSentence;
        BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); // user input

        Socket clientSocket = new Socket("localhost", TCPServer.portNum); // 서버의 IP 주소와 포트 번호

        DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); // 서버한테 보낼 output
        BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); // 서버한테서 읽어들일 input

        System.out.println("서버에 보낼 메시지를 입력하세요: ");
        sentence = inFromUser.readLine();   // 유저한테 입력 받은 문자열 저장

        //outToServer.writeBytes(sentence + "\n"); // 한글 깨짐
        outToServer.write((sentence + "\n").getBytes()); // 입력 받은 문자열 서버에 write
        modifiedSentence = inFromServer.readLine(); // 서버한테 받은 문자열 저장

        System.out.println("서버로부터의 응답: " + modifiedSentence);

        clientSocket.close();
    }
}

UDP

User Datagram Protocol
보안과 신뢰성보다 전송 속도와 효율성이 더 중요한 경우 데이터를 전송하기 위해 IP와 함께 사용되는 프로토콜

  • 비연결형 방식
  • 낮은 신뢰성
  • TCP보다 빠른 속도
  • 정보의 신호 절차를 거치지 않음
  • 데이터 순서 보장
  • 스트리밍, 온라인 게임 등 실시간 서비스에 적합

예제

Server

package ch4.socket.server;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class UDPServer {
    public static void main(String[] args) {
        DatagramSocket socket = null;
        try {
            // 클라이언트 연결을 기다리는 과정 없이 바로 데이터 수신 준비가 완료
            socket = new DatagramSocket(9876);
            byte[] receiveData = new byte[1024];

            while(true) {
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                socket.receive(receivePacket);

                String message = new String(receivePacket.getData(), 0, receivePacket.getLength());
                System.out.println("수신된 클라이언트 메시지: " + message);
            }
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                socket.close();
            }
        }
    }
}

Client

package ch4.socket.client;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

public class UDPClient {
    public static void main(String[] args) {
        DatagramSocket socket = null;
        try {
            socket = new DatagramSocket();
            InetAddress IPAddress = InetAddress.getByName("localhost");
            byte[] sendData = new byte[2];
            String sentence = "Hello UDP Server";
            sendData = sentence.getBytes();

            DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
            socket.send(sendPacket);

            byte[] receiveData = new byte[1024];
            DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
            socket.receive(receivePacket);
            String modifiedSentence = new String(receivePacket.getData(), 0, receivePacket.getLength());
            System.out.println("서버 메시지: " + modifiedSentence);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socket != null) {
                socket.close();
            }
        }
    }
}

TCP VS UDP

TCP UDP
연결 방식 연결형 비연결형
전송 순서 순서 보장 순서 보장 X
수신 여부 확인 O X
통신 방식 1:1 1:1, 1:N, N:N
신뢰성 높다 낮다
속도 느리다 빠르다
profile
어중이떠중이

0개의 댓글