Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Archives
Today
Total
관리 메뉴

Code Habit

golang ) TCP Server/Client 구현하기 본문

카테고리 없음

golang ) TCP Server/Client 구현하기

코드베어 2020. 6. 18. 09:55

golang에서 "net" 패키지에서 TCP 프로토콜을 제공한다. 

 

간단히 TCP 프로토콜 에코서버와 클라이언트를 만들어 보겠다.

 

서버 예제

// main.go
package main
 
import (
    "fmt"
    "io"
    "net"
)
 
func handler(conn net.Conn) {
    recv := make([]byte4096)
 
    for {
        n, err := conn.Read(recv)
        if err != nil {
            if err == io.EOF {
                fmt.Println("connection is closed from client : ", conn.RemoteAddr().String())
            }
            fmt.Println("Failed to receive data : ", err)
            break
        }
 
        if n > 0 {
            fmt.Println(string(recv[:n]))
            conn.Write(recv[:n])
        }
    }
}
 
func main() {
    l, err := net.Listen("tcp"":8000")
    if err != nil {
        fmt.Println("Failed to Listen : ", err)
    }
    defer l.Close()
 
    for {
        conn, err := l.Accept()
        if err != nil {
            fmt.Println("Failed to Accept : ", err)
            continue
        }
 
        go handler(conn)
    }
}

net.Listen() 함수로 8000번 포트로 "tcp" 서버를 개설하고 리턴된 l ( net.Conn ) 의 Accept() 함수로 사용자의 접속을 대기한다. 대기 중 사용자가 접속하면 해당 커넥션을 handler 함수로 처리한다.  handler 함수에서 Read() 함수로 사용자의 전송을 대기하며 데이터가 들어오면 이를 출력 한 뒤 다시 보낸다.

 

클라이언트 예제

// main.go
package main
 
import (
    "fmt"
    "net"
    "time"
)
 
func main() {
    conn, err := net.Dial("tcp""127.0.0.1:8000")
    if err != nil {
        fmt.Println("Faield to Dial : ", err)
    }
    defer conn.Close()
 
    go func(c net.Conn) {
        send := "Hello"
        for {
            _, err = c.Write([]byte(send))
            if err != nil {
                fmt.Println("Failed to write data : ", err)
                break;
            }
 
            time.Sleep(1 * time.Second)
        }
    }(conn)
 
    go func(c net.Conn) {
        recv := make([]byte4096)
 
        for {
            n, err := c.Read(recv)
            if err != nil {
                fmt.Println("Failed to Read data : ", err)
                break
            }
 
            fmt.Println(string(recv[:n]))
        }
    }(conn)
 
    fmt.Scanln()
}

Dial() 함수를 통해 로컬에 8000번 tcp 서버에 연결하고 연결이 성공하면 데이터를 보내는/받는 고루틴 (익명)함수를 실행 한다. 1초마다 "Hello"라는 문자를 보내고 이에 대한 응답을 받아 출력해준다.

 

* 위 예제는 간단한 에코 데이터를 처리하는 예제로 실제 실무에서는 패킷 길이에 대한 정보와 읽어온 데이터의 길이등을 계산해 주어야 한다. 

 

다음은 위 예제에 사용된 함수들이다.

  • func Listen(net, laddr string) (Listener, error) : 프로토콜, IP 주소, 포트 번호를 설정하여 네트워크 연결을 대기.
  • func (I *TCPListener) Accept() (Conn, error) : 클라이언트가 연결되면 커넥션을 리턴.
  • func (I *TCPListener) Close() error : TCP 연결 대기를 닫음.
  • func Dial(net, address string) (Conn, error) : 프로토콜, IP 주소, 포트 번호를 설정하여 서버에 연결.
  • func (c *TCPConn) Close() error : TCP 연결을 닫음.
  • func (c *TCPConn) Read(b []byte)(int, error) : 받은 데이터를 읽음.
  • func (c *TCPConn) Write(b []byte)(int, error) : 데이터를 보냄.