본문 바로가기
Engineering WIKI/Java

[Java] 소켓 통신이란? [자바 코드 포함]

by wonos 2020. 12. 6.

소켓 이란?

  • 소켓 → 프로토콜, ip주소, 포트넘버로 정의 됨.
  • 떨어져 있는 두 호스트를 연결해주는 도구로써 인터페이스 역할.
  • 데이터를 주고 받을 수 있는 구조체로 소켓을 통해 데이터 통로가 만들어 진다.
  • 소켓의 역할에 따라 클라이언트 소켓, 서버소켓으로 구분된다.

소켓 통신의 흐름

서버

  • 클라이언트 소켓의 연결 요청을 대기하고, 연결요청이 오면 클라이언트 소켓을 생성하여 통신이 가능하게 한다.
  1. socket()함수를 이용하여 소켓 생성
  2. bind()함수로 ip와 port 번호 설정
  3. listen()함수로 클라이언트의 접근 요청에 수신 대기열을 만들어 몇 개의 클라이언트를 대기 시킬지 결정.
  4. accept()함수를 사용하여 클라이언트와의 연결을 기다림.

클라이언트

  • 실제로 데이터 송수신이 일어나는 것은 클라이언트 소켓이다.
  1. socket() 함수로 가장먼저 소켓을 연다.
  2. connect() 함수를 이용하여 통신 할 서버의 ip와 port 번호에 통신을 시도.
  3. 통신 시도시, 서버가 accept() 함수를 이용하여 클라이언트의 socket descriptor를 반환.
  4. 이를 통해 클라이언트와 서버가 read(), write()를 하며 통신 ( 반복 )

소켓 종류

TCP

  • 양방향으로 바이트 스트림을 전송, 연결 지향성
  • 오류 수정, 전송 처리, 흐름제어 보장
  • 송신된 순서에 따라 중복되지 않게 데이터를 수신 → 오버헤드 발생
  • 소량의 데이터보다 대량의 데이터에 적합

UDP

  • 비연결형 소켓
  • 데이터의 크기에 제한이 있음.
  • 확실하게 전달이 보장되지 않음. → 데이터가 손실되도 오류 발생 안됨.
  • 실시간 멀티미디어 정보를 처리하기 위해 주로 사용 → 전화

HTTP 통신과 SOCKET 통신의 비교

HTTP 통신

  • Client의 요청(Request)가 있을때 서버가 응답(Response)하여 해당 정보를 전송하고 곧바로 연결 종료.
  • HTTP 통신의 특징
    • Client가 요청을 보낼때만 서버가 응답하는 단방향 통신
    • Server로 부터 응답을 받은 후 바로 연결종료.
    • 실시간 연결이 아니고, 필요한 경우에만 Server로 요청을 보내는 상황에 유용.
    • 요청을 보내 Server의 응답을 기다리는 어플리케이션의 개발에 주로 사용.

Socket 통신

  • Server와 Client가 특정 port를 통해 실시간으로 양방향 통신
  • SOCKET 통신의 특징
    • 서버와 클라이언트가 계속 연결을 유지하는 양방향 통신
    • 서버와 클라이언트가 실시간으로 데이터를 주고 받는 상황이 필요한 경우에 사용
    • 실시간 동영상 스트리밍이나 온라인 게임등과 같은 경우에 주로 사용.

클라이언트 소켓 코드

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
 
public class Client {
     
    final static String SERVER_IP = "127.0.0.1"; 
    final static int SERVER_PORT = 1225;
    final static String MESSAGE_TO_SERVER = "Hi, Server";
     
    public static void main(String[] args) {
         
        Socket socket = null;
         
        try {
            /** 소켓통신 시작 */
            socket = new Socket(SERVER_IP,SERVER_PORT);
            System.out.println("socket 연결");
         
            /** Client에서 Server로 보내기 위한 통로 */
            OutputStream os = socket.getOutputStream();
            /** Server에서 보낸 값을 받기 위한 통로 */
            InputStream is = socket.getInputStream();
             
            os.write( MESSAGE_TO_SERVER.getBytes() );
            os.flush();
             
            byte[] data = new byte[16];
            int n = is.read(data);
            final String resultFromServer = new String(data,0,n);
             
            System.out.println(resultFromServer);
             
            socket.close();
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
         
    }
}

서버 소켓 코드

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
public class Serverextends Thread {
     
    final static int SERVER_PORT =1225;
    final static String MESSAGE_TO_SERVER ="Hello, Client";
     
    public static void main(String[] args) {
         
        ServerSocket serverSocket =null;
         
        try {
            serverSocket =new ServerSocket(SERVER_PORT);
             
             
        }catch (IOException e) {
            e.printStackTrace();
        }
         
        try {
            while (true) {
                System.out.println("socket 연결 대기");
                Socket socket = serverSocket.accept();
                System.out.println("host : "+socket.getInetAddress()+" | 통신 연결 성공");
                 
                /** Server에서 보낸 값을 받기 위한 통로 */
                InputStream is = socket.getInputStream();
                /** Server에서 Client로 보내기 위한 통로 */
                OutputStream os = socket.getOutputStream();
                 
                byte[] data =new byte[16];
                int n = is.read(data);
                final String messageFromClient =new String(data,0,n);
                 
                System.out.println(messageFromClient);
                 
                os.write( MESSAGE_TO_SERVER.getBytes() );
                os.flush();
                 
                is.close();
                os.close();
                socket.close();
            }
             
        }catch (IOException e) {
            e.printStackTrace();
        }
         
    }
}
 
class SocketRunimplements Runnable {
 
    private Socket socket =null;
     
    SocketRun( Socket socket ){
        this.socket = socket;
    }
     
    @Override
    public void run() {
         
    }
}