GoLang_TCP Socket Communication

wldbs._.·2024년 10월 29일

GoLang

목록 보기
5/6
post-thumbnail

Go Package : net
ChatGPT

mqtt 프로젝트를 진행하며, 별도의 TCP 소켓을 열어 메시지를 전달해야 하는 과제가 생겨
이전에 알아보다가 말았던 소켓을 적용하고자 한다.

Go에서 소켓 통신을 활용하기 위해서는 net 패키지를 활용해야 한다.
차근차근 정리해보자.



1. net package

Go 언어에서 네트워크 통신을 수행하기 위해 net 패키지를 사용한다.

  • 이 패키지는 다양한 프로토콜을 지원하며, TCP, UDP, IP, HTTP 등 여러 네트워크 프로토콜을 구현하는 데 사용된다.
  • net 패키지를 통해 소켓 생성, 서버-클라이언트 간 연결 관리, 데이터 송수신 등의 기능을 손쉽게 구현할 수 있다.


2. socket communication

소켓 통신은 두 컴퓨터 또는 애플리케이션 간 양방향 통신을 제공하는 메커니즘이다.

  • 소켓은 IP 주소포트 번호를 사용해 네트워크 연결을 설정하며, 데이터 송수신 경로를 제공
  • TCP/IP 같은 네트워크 프로토콜에서 소켓을 활용해 클라이언트와 서버 간 데이터 전송이 이루어짐


3. TCP socket communication

TCP(Transmission Control Protocol)는 연결 지향형 프로토콜로, 데이터 전송의 신뢰성과 순서 보장을 제공한다.

  • 클라이언트가 서버와 연결을 맺고 데이터를 주고받는 방식으로 통신
  • 각 연결은 고유한 소켓을 사용

[TCP 소켓 통신 과정]

1. 서버 측

  • 서버는 소켓을 열고 지정된 포트에서 연결 요청을 기다린다.
  • 클라이언트가 연결을 시도하면, 서버는 해당 연결을 수락(Accept) 하고 데이터를 송수신한다.

2. 클라이언트 측

  • 클라이언트는 Dial 함수를 사용해 서버의 IP와 포트에 연결을 시도한다.
  • 연결이 성공하면 데이터를 전송하거나 수신할 수 있다.


4. Go - s.c


Go 언어의 net 패키지를 사용해 TCP 서버와 클라이언트를 구현할 수 있다.

import (
	"bufio"
	"fmt"
	"log"
	"net"
)

[1] Server (Listen and Accept)

listener, err := net.Listen("tcp", "localhost:8080") // 서버 소켓 생성 및 포트 바인딩
// net.Listen(protocol, address) : tcp protocol, IP주소(localhost):포트(-p)
// listener 객체 : 클라이언트의 연결을 대기, 서버 소켓 역할 수행, Accept() 호출해 클라이언트의 연결 요청 수락
if err != nil {
// %v : 해당 값에 맞는 기본 형식으로 출력해주는 역할 [에러 메시지를 있는 그대로 깔끔하게 출력]
    log.Fatalf("Failed to start server: %v", err)
}
defer listener.Close() // 함수 종료 시 리스너 자원 해제

// 클라이언트 연결 요청 대기
fmt.Println("Waiting for client connection...")
// 새로운 연결이 들어오면 해당 요청을 수락하고, 연결 객체 conn을 반환 (연결 실패 시 에러 반환)
conn, err := listener.Accept() // 클라이언트 연결 수락
if err != nil {
    log.Fatalf("Failed to accept connection: %v", err)
}
defer conn.Close() // // 연결 종료 시 자원 해제

fmt.Println("Client connected!")
  • Listen: 서버 소켓을 생성하고 지정된 IP 주소와 포트에 바인딩
  • Accept: 클라이언트가 연결 요청을 보내면 서버는 이를 수락

서버는 여러 클라이언트와 동시에 통신하기 위해 다중 연결을 처리해야 할 수 있다.

ListenAccept

  • Listen: 서버 소켓이 특정 포트에서 연결 요청을 받을 수 있도록 준비 상태로 만든다.
    • 일반적으로 서버 소켓 초기화 후에 바로 호출하여 포트에서 대기
    • listen은 소켓 서버가 클라이언트의 연결 요청을 대기할 준비가 되었음을 나타냄
    • 이를 통해 서버는 특정 포트에서 들어오는 연결 요청을 수신할 수 있음
    • 서버 소켓을 연결 대기 상태로 만들어 -> 특정 포트에 대한 클라이언트 요청을 받을 준비를 함
  • Accept: 들어오는 클라이언트 연결 요청을 실제로 수락하여, 클라이언트와의 통신을 시작할 수 있는 소켓을 반환한다.
    • listen이 활성화된 포트로 들어온 클라이언트의 연결 요청을 수락하는 함수
    • 클라이언트와 서버 간의 개별 연결을 처리하며, 성공적으로 연결되면 새로운 소켓을 반환하여 클라이언트와 직접 통신할 수 있게 함
    • 클라이언트 요청을 수락하고, 서버가 클라이언트와 통신할 수 있도록 개별 연결 소켓을 생성
    • 일반적으로 listen 이후에 사용되며, 클라이언트가 연결을 요청할 때까지 블로킹 상태로 대기

[2] Client (Dial)

// Dial을 사용해 서버에 연결
conn, err := net.Dial("tcp", "localhost:8080") // 서버와의 연결 시도
if err != nil {
    log.Fatalf("Failed to connect to server: %v", err)
}
defer conn.Close()

fmt.Println("Connected to server!")
  • Dial: 클라이언트는 서버의 IP와 포트에 연결을 시도

연결이 성공하면 클라이언트와 서버 간의 양방향 데이터 전송이 가능해진다.


[3] Data Send-Receive

서버와 클라이언트 간 데이터 송수신은 WriteRead 함수를 통해 이루어진다.

1. 데이터 송신 (클라이언트 → 서버)

message := "Hello, Server!"

conn.Write([]byte(message)) // 서버로 데이터 전송

2. 데이터 수신 (서버에서 데이터 수신)

buffer := make([]byte, 1024) // 수신 버퍼 생성
n, err := conn.Read(buffer)  // 클라이언트로부터 데이터 읽기

if err != nil {
    log.Fatalf("Failed to read data: %v", err)
}
fmt.Printf("Received: %s\n", string(buffer[:n]))
  • Write: 연결된 소켓을 통해 데이터를 전송
  • Read: 수신된 데이터를 버퍼에 저장하고, 읽은 바이트 수를 반환


5. 정리 및 요약

< 소켓 통신 활용의 이점 >
1. 실시간 통신: 서버와 클라이언트 간 빠르고 실시간으로 데이터를 주고받을 수 있다.
2. 양방향 연결: 클라이언트와 서버 모두 데이터 송수신이 가능하다.
3. 다중 연결 지원: 여러 클라이언트가 동시에 서버에 연결할 수 있다.

<TCP 소켓 통신과 Go의 net 패키지 활용 요약>
1. Go의 net 패키지는 소켓 통신을 간단하고 직관적으로 구현할 수 있게 해준다.
2. TCP 소켓 통신을 통해 연결의 신뢰성을 보장하며, MQTT와 같은 프로토콜과 병행하여 사용하면 다양한 통신 시나리오를 처리할 수 있다.

Go의 net 패키지를 사용한 TCP 소켓 통신은 발행자와 구독자 간의 직접적인 메시지 전달에 유용하다.
내 프로젝트에서는 MQTT 브로커와 소켓을 조합해 메시지를 처리함으로써 효율적이고 신뢰성 있는 통신을 구현했다.

profile
공부 기록용 24.08.05~ #LLM #RAG

0개의 댓글