소켓
논리적인 의미의 소켓은 컴퓨터 네트워크를 경유하는 프로세스간 통신의 종착점을 의미하며 서로 네트워크를 이용해 데이터를 송수신할경우 최종적으로 거치게되는 endpoint를 뜻한다.
클라이언트
- socket() 함수를 호출하여 클라이언트 소켓을 생성
- connect() 함수를 호출하여 서버 소켓에 연결을 요청 - 서버의 IP 주소와 포트 번호를 사용하여 연결을 시도
- send() 함수를 사용하여 데이터를 서버로 전송, recv() 함수를 사용하여 서버로부터 데이터를 수신
- 통신이 완료되면 close() 함수를 호출하여 소켓을 닫고 연결을 종료
서버
- socket() 함수를 호출하여 서버 소켓을 생성
- bind() 함수를 사용하여 생성된 소켓을 특정 IP 주소와 포트 번호에 바인딩 ->서버가 특정 네트워크 인터페이스와 포트에서 요청을 수신할 수 있도록 설정
- listen() 함수를 호출하여 소켓을 수신 대기 상태로 변경
- accept() 함수를 사용하여 클라이언트의 연결 요청을 수락
- send() 함수를 사용하여 데이터를 클라이언트로 전송, recv() 함수를 통해 클라이언트로부터 데이터를 수신
- 통신이 완료되면 close() 함수를 호출하여 소켓을 닫고 연결을 종료
역할과 위치
소켓은 OSI 7계층 중 실제 유저들과 상호작용하는 응용 계층(application layer)과 데이터를 송수신하는 전송 계층(transport layer)사이에 위치하며, 응용 프로그램이 데이터를 송수신하기 위해 TCP/IP를 사용하는 인터페이스 역할을 담당한다.
한 프로세스는 여러 개의 소켓을 사용할 수 있으며 소켓 번호를 통해 각 소켓을 구분하며 하나의 호스트에서 여러 호스트와 동시에 통신할 수 있습니다.
또한 통신을 통해 전달되는 모든 데이터 포맷은 5-tuple 이라는 규격에 맞추어 진행되며 여기에 필요로 하는것은 크게 IP 주소와 포트 번호를 필요로한다.
- IP 주소: 데이터를 송신할 호스트를 식별.
- 포트 번호: 호스트 내의 특정 프로세스를 식별.
- TCP: 데이터 전송 전에 연결을 설정하여 신뢰성 있는 통신을 제공합니다.
5-tuple
- 프로토콜 (Protocol)
- 호스트 IP 주소 (source IP address)
- 호스트 port 번호 (source port nunber)
- 목적지 IP 주소 (destination IP address)
- 목적지 port 번호 (destination port number)
server-client 구조
TCP/UDP 위에서 동작하므로 당연하게 server-client 통신 구조를 갖춘다.
처음에 데이터를 보내는 쪽이 client가 되고, 받는 쪽이 server가 된다. 이후에는 서로가 데이터를 송수신할 수 있다. (자세한 설명은 아래)
양방향 통신
socket은 한 쪽에서 데이터를 보내고 반대 편에서 이를 수신한 뒤 연결이 끊어지는게 아니라 양 쪽에서 실시간으로 데이터를 송수신할 수 있다. 따라서 실시간 스트리밍이나 채팅에 주로 유용하게 사용된다.
프로그래밍 언어나 운영체제에 종속적
socket은 TCP/IP 표준이 아니라 네트워크 프로그래밍 인터페이스다. 따라서 운영체제마다 사용법이 약간씩 다르며, 그 안에서 또 프로그래밍 언어마다 소켓 api 를 구현한 라이브러리가 다 다르다.
JAVA의 경우
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
Socket clientSocket = serverSocket.accept();
OutputStream output = clientSocket.getOutputStream();
PrintWriter writer = new PrintWriter(output, true);
writer.println("Welcome to the server!");
clientSocket.close();
}
}
}
Node의 경우
const net = require('net');
const server = net.createServer((socket) => {
console.log('Connection from', socket.remoteAddress, 'has been established.');
socket.write('Welcome to the server!\n');
socket.end();
});
server.listen(8080, () => {
console.log('Server is listening on port 8080...');
});
HTTP가 웹에서 데이터를 교환하기 위한 프로토콜이라고 하였다.
해당 방식은 클라이언트가 요청을 보내면 서버가 해당 요청에 따른 응답을 반환하지만 HTTP의 특성인 무연결성으로 인하여 신규 데이터가 등록되더라도 사용자가 이를 보기 위해선 항상 새로운 요청을 보내야 등록된 데이터를 가져올수 있었다. (매 요청마다 새로운 연결을 생헝하고 응답후 연결을 끊는 방식)
그렇다면 실시간으로 채팅을 구현하기 위해선 어떤 방식을 활용해야 핳까?
웹소켓
기존 HTTP의 무연결성을 해결하여 서버와 브라우저간 양방향 통신이 가능하게 해주는 기술로 한번 연결이 설정되면 끊어질때까지 서버와 클라이언트 모두 데이터를 전송할수 있게된다
- 저지연: 데이터를 즉각적으로 전송할 수 있다
- HTTP 호환성: 웹소켓 연결은 HTTP 요청을 통해 시작되며, ws 또는 보안 연결인 wss 프로토콜을 사용
- 효율적인 자원 사용: 한 번의 연결 설정으로 지속적인 데이터 교환을 할 수 있어 자원 사용이 효율적입니다. (반복적인 handshake 생략)
동작방식
- 연결초기화
- HTTP 요청을 사용해 서버에 연결하며 Upgrade: websocket 헤더를 포함해 해당 요청이 웹소켓임을 알리며 이에 맞도록 http요청을 웹소켓 연결로 업그레이드
- HTTP GET 요청에 Upgrade: websocket, Connection: Upgrade 포함되며 해당 헤더는 웹소켓 프로토콜의 업그레이드를 의미한다.
- 서버는 HTTP/1.1 101 Switching Protocols 상태 코드와 함께 웹소켓으로 업그레이드 요청을 수락한다는 의미의 Upgrade: websocket 및 Connection: Upgrade 헤더를 포함시킵니다.
- 핸드셰이크 응답
- 서버가 요청을 수락하면 http 응답에 Upgrade: websocket 헤더를 포함해 웹소켓 프로토콜로 업그레이드 후 클라이언트에 다시 전달 (TCP 기반 프로토콜)
- 데이터 교환(연결된 상태)
- 연결이 될경우 클라이언트와 서버는 네트워크 지연 없이 실시간으로 메세지를 교환할수 있으며 메세지는 텍스트 또는 바이너리 형태가 될수있다.
- 연결 종료
- 어느 한쪽이든 연결 종료가 가능하며 종료과정이 합의된 프로토콜에 따라 이뤄진다.
웹소켓 (WebSocket): 웹소켓은 OSI 모델의 응용 계층에 속하며 웹 애플리케이션 실시간 통신을 가능하게 하는 프로토콜이다.
HTTP를 기반으로 초기 연결을 수립한 뒤 웹소켓 프로토콜로 업그레이드하여 데이터를 교환합니다. 웹소켓 프로토콜은 HTTP와 같은 다른 응용 계층 프로토콜 위에서 동작하면서도, 그 자체로 응용 계층의 기능을 수행합니다.
'Spring' 카테고리의 다른 글
Jmeter - 1 (0) | 2024.06.08 |
---|---|
배포흐름 (0) | 2024.05.26 |
스프링 시큐리티 (0) | 2024.02.20 |
웹에서 핸드폰으로 메세지 보내기 - 2 (0) | 2024.02.05 |
웹에서 핸드폰으로 메세지 보내기 - 1 (0) | 2024.02.05 |