TCP Keepalive 개요
Go의 net 패키지는 TCP keepalive의 유휴 시간, 프로빙 간격, 시도 횟수를 직접 설정하는 기능을 제공하지 않습니다. 이러한 설정을 구현하기 위해 서드파티 패키지를 활용할 수 있습니다.
패키지 설치
go get github.com/felixge/tcpkeepalive
서버 구현 예제
클라이언트 연결 수락 후 keepalive 매개변수 설정:
- 유휴 시간(Idle): 10초
- 프로빙 간격(Interval): 10초
- 프로빙 횟수(Count): 9회
package main
import (
"log"
"net"
"time"
tk "github.com/felixge/tcpkeepalive"
)
func main() {
listener, err := net.Listen("tcp", "0.0.0.0:8080")
if err != nil {
log.Fatal("리스너 오류:", err)
}
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
log.Println("연결 수락 실패:", err)
continue
}
go processClient(conn)
}
}
func enableKeepAlive(conn net.Conn) (*tk.Conn, error) {
kaConn, err := tk.EnableKeepAlive(conn)
if err != nil {
return nil, err
}
if err := kaConn.SetKeepAliveIdle(10 * time.Second); err != nil {
return nil, err
}
if err := kaConn.SetKeepAliveInterval(10 * time.Second); err != nil {
return nil, err
}
if err := kaConn.SetKeepAliveCount(9); err != nil {
return nil, err
}
return kaConn, nil
}
func processClient(conn net.Conn) {
defer conn.Close()
kaConn, err := enableKeepAlive(conn)
if err != nil {
log.Println("Keepalive 설정 실패:", err)
return
}
msg := []byte("서버 응답 메시지")
for {
if _, err := kaConn.Write(msg); err != nil {
log.Println("전송 오류:", err)
return
}
time.Sleep(5 * time.Second)
}
}
클라이언트 구현 예제
package main
import (
"fmt"
"net"
"os"
)
func main() {
conn, err := net.Dial("tcp", "localhost:8080")
if err != nil {
fmt.Println("연결 실패:", err)
os.Exit(1)
}
defer conn.Close()
buf := make([]byte, 1024)
for {
n, err := conn.Read(buf)
if err != nil {
fmt.Println("수신 오류:", err)
return
}
fmt.Printf("수신: %d바이트 | 내용: %s\n", n, string(buf[:n]))
}
}
동작 검증 방법
서버 출력:
2023/03/15 10:00:00 전송 성공: 18바이트
클라이언트 출력:
수신: 18바이트 | 내용: 서버 응답 메시지
tcpdump 또는 Wireshark로 TCP Keep-Alive 패킷 관찰 가능