Go

Go - 간단한 Echo Server / Client

Hewii 2021. 8. 31. 13:34

Go TCP Echo Server / Client 기본

 

기존 C++, C#, Python, Swift 등으로 네트워크 프로그래밍을 통해 여러 서비스를 개발 해봤지만 Go는 다른 언어와 다르게 매우 편하게 기본 구성을 잡을 수 있었다.

 

과거에 Go 언어가 지원되는 프레임워크나 기능등이 적어 관심이 적었으나 최근에 어떤 프로젝트를 진행하면서 Go로 이뤄져 있는 오픈 소스를 분석하고 커스텀 해야할 일이 생겨서 GO 언어를 접하게 되었다. 

 

기본 적인 사용법을 훑어보고 맛보기로 테스트 코딩을 하면서 느낀 장점이 있었다

 

장점

- Go 루틴으로 인해 NonBlock 처리가 매우 편하다.

- Python과 같이 배열 Slice 기능으로 패킷 처리가 매우 편하다.

 

 

-- Client --

package main

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

func main() {
	conn, err := net.Dial("tcp", ":9001")
    // "tcp", "tcp4", "tcp6", "unix" or "unixpacket". 로 설정 가능

	if err != nil {
		log.Fatalf("Fialed to bind port ")
	}

	go StartReceive(conn)

	for {
		var s string
		fmt.Scanln(&s)
		conn.Write([]byte(s))
	}
}

func StartReceive(conn net.Conn) {
	recvBuf := make([]byte, 8192)

	for {
		n, err := conn.Read(recvBuf)

		if err != nil || n <= 0 {
			log.Println(err)
			return
		}

		log.Println("From server : ", string(recvBuf[:n]))
	}
}

 

 

-- Server --

package main

import (
	"io"
	"log"
	"net"
)

func main() {
	l, err := net.Listen("tcp", ":9001")

	if err != nil {
		log.Fatalf("Fialed to bind port ")
	}

	defer l.Close()

	for {
		conn, err := l.Accept()
		if nil != err {
			log.Print("Failed Accept ", err)
		}

		go ConnHandler(conn)
	}
}

func ConnHandler(conn net.Conn) {
	recvBuf := make([]byte, 8192)

	for {
		n, err := conn.Read(recvBuf)

		if err != nil || n <= 0 {
			if io.EOF == err {
				log.Printf("Disconnect client %v", conn.RemoteAddr().String())
				return
			}

			log.Printf("Failed Received data : err : %v", err)
			return
		}

		data := recvBuf[:n]
		log.Println(string(data))
		conn.Write(data)
	}
}