네트워크 프로그래밍에서는 연결 또는 데이터 전송이 지연되는 경우를 방지하기 위해 타임아웃 설정이 필수적입니다. 이 문서에서는 Go 언어로 네트워크 연결 및 읽기/쓰기 타임아웃을 설정하는 방법에 대해 설명합니다.
1. 타임아웃 설정
1.1 연결 타임아웃
DialTimeout 함수는 네트워크 연결 시 타임아웃을 설정하는 데 사용됩니다.
func DialTimeout(network, address string, timeout time.Duration) (Conn, error)
위 함수에서 timeout 매개변수는 연결이 완료되기까지 기다리는 최대 시간을 지정합니다. 설정된 시간을 초과하면 타임아웃 오류가 반환됩니다.
1.2 읽기/쓰기 타임아웃
Conn 인터페이스에는 읽기와 쓰기 동작에 대한 타임아웃 설정 메서드가 포함되어 있습니다.
type Conn interface {
SetDeadline(t time.Time) error
SetReadDeadline(t time.Time) error
SetWriteDeadline(t time.Time) error
}
각 메서드는 특정 시간 이후의 작업을 제한하며, 해당 시간 이후에도 작업이 완료되지 않으면 타임아웃 오류가 발생합니다. 매번 새로운 시간을 설정해야 하며, 이를 갱신하지 않을 경우 계속해서 타임아웃 상태에 있을 수 있습니다.
2. 예제 코드
2.1 서버(SERVER)
아래 서버 코드는 클라이언트와 연결 후 데이터를 주고받습니다. 쓰기 작업 전에 일부 지연(3초)을 추가하여 타임아웃 테스트를 수행합니다.
package main
import (
"log"
"net"
"time"
)
func main() {
addr := "0.0.0.0:8080"
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
log.Fatalf("ResolveTCPAddr 실패: %s", addr)
}
listener, err := net.ListenTCP("tcp", tcpAddr)
if err != nil {
log.Fatalf("리스닝 실패: %s", addr)
}
log.Println("서버 시작:", addr)
for {
conn, err := listener.Accept()
if err != nil {
log.Println("연결 수락 실패:", err)
continue
}
go handleConnection(conn)
}
}
func handleConnection(conn net.Conn) {
defer conn.Close()
message := []byte("안녕하세요! 저는 서버입니다.")
for {
time.Sleep(3 * time.Second) // 3초 대기
n, err := conn.Write(message)
if err != nil {
log.Println("데이터 전송 실패:", err)
break
}
log.Println("전송 완료:", n, "바이트")
}
}
2.2 클라이언트(CLIENT)
클라이언트는 연결 시 3초의 타임아웃을 설정하고, 읽기 작업마다 타임아웃을 재설정합니다.
package main
import (
"log"
"net"
"os"
"time"
)
func main() {
connTimeout := 3 * time.Second
conn, err := net.DialTimeout("tcp", "127.0.0.1:8080", connTimeout)
if err != nil {
log.Println("연결 실패:", err)
os.Exit(1)
}
defer conn.Close()
readTimeout := 2 * time.Second
buffer := make([]byte, 512)
for {
deadline := time.Now().Add(readTimeout)
err = conn.SetReadDeadline(deadline)
if err != nil {
log.Println("타임아웃 설정 실패:", err)
}
n, err := conn.Read(buffer)
if err != nil {
log.Println("읽기 실패:", err)
} else {
log.Printf("읽은 데이터: %d 바이트, 내용: %s", n, string(buffer[:n]))
}
}
}
3. 실행 결과
클라이언트는 2초의 읽기 타임아웃으로 설정되어 있으며, 서버가 3초마다 데이터를 보내므로 일부 읽기 작업에서 타임아웃이 발생합니다.
2023/10/10 14:18:19 읽기 실패: read tcp 127.0.0.1:51718->127.0.0.1:8080: i/o timeout
2023/10/10 14:18:23 읽은 데이터: 28 바이트, 내용: 안녕하세요! 저는 서버입니다.
2023/10/10 14:18:25 읽기 실패: read tcp 127.0.0.1:51718->127.0.0.1:8080: i/o timeout
타임아웃 설정을 통해 네트워크 지연 문제를 효과적으로 관리할 수 있습니다.