TCP 프로토콜 사용하기

이재홍 http://www.pyrasis.com 2014.12.17 ~ 2015.02.07

클라이언트 작성하기

이제 클라이언트를 작성합니다.

다음은 net 패키지에서 제공하는 TCP 함수입니다.

  • func Dial(network, 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): 데이터를 보냄

다음 내용을 GOPATH/src/tcpclient/tcpclient.go 파일로 저장합니다.

GOPATH/src/tcpclient/tcpclient.go

package main

import (
	"fmt"
	"net"
	"strconv"
	"time"
)

func main() {
	client, err := net.Dial("tcp", "127.0.0.1:8000") // TCP 프로토콜, 127.0.0.1:8000 서버에 연결
	if err != nil {
		fmt.Println(err)
		return
	}
	defer client.Close() // main 함수가 끝나기 직전에 TCP 연결을 닫음

	go func(c net.Conn) {
		data := make([]byte, 4096) // 4096 크기의 바이트 슬라이스 생성

		for {
			n, err := c.Read(data) // 서버에서 받은 데이터를 읽음
			if err != nil {
				fmt.Println(err)
				return
			}

			fmt.Println(string(data[:n])) // 데이터 출력

			time.Sleep(1 * time.Second)
		}
	}(client)

	go func(c net.Conn) {
		i := 0
		for {
			s := "Hello " + strconv.Itoa(i)

			_, err := c.Write([]byte(s)) // 서버로 데이터를 보냄
			if err != nil {
				fmt.Println(err)
				return
			}

			i++
			time.Sleep(1 * time.Second)
		}
	}(client)

	fmt.Scanln()
}

예제를 좀 더 명확하게 하고자 이 클라이언트는 서버에 데이터를 보내는 고루틴과 서버에서 받은 데이터를 출력하는 고루틴 두 부분으로 구성되어 있습니다.

먼저 net.Dial 함수에 tcp와 서버의 IP 주소 및 포트 번호를 설정합니다. 서버에 연결되면 net.Conn이 리턴되고 데이터를 받거나 보낼 수 있습니다. 지연 호출을 사용하여 클라이언트가 끝나면 TCP 연결을 닫아줍니다.

client, err := net.Dial("tcp", "127.0.0.1:8000") // TCP 프로토콜, 127.0.0.1:8000 서버에 연결
if err != nil {
	fmt.Println(err)
	return
}
defer client.Close() // main 함수가 끝나기 직전에 TCP 연결을 닫음

서버에 데이터를 보내는 고루틴입니다. 마찬가지로 TCP 연결 cWrite 함수로 서버에 데이터를 보냅니다. 여기서는 1초마다 Hello 문자열에 숫자를 1씩 증가시켜서 보냅니다.

go func(c net.Conn) {
	i := 0
	for {
		s := "Hello " + strconv.Itoa(i)

		_, err := c.Write([]byte(s)) // 서버로 데이터를 보냄
		if err != nil {
			fmt.Println(err)
			return
		}

		i++
		time.Sleep(1 * time.Second)
	}
}(client)

서버에서 데이터를 받은 뒤 출력하는 고루틴입니다. Read 함수로 서버에서 받은 데이터를 가져옵니다.

go func(c net.Conn) {
	data := make([]byte, 4096) // 4096 크기의 바이트 슬라이스 생성

	for {
		n, err := c.Read(data) // 서버에서 받은 데이터를 읽음
		if err != nil {
			fmt.Println(err)
			return
		}

		fmt.Println(string(data[:n])) // 데이터 출력

		time.Sleep(1 * time.Second)
	}
}(client)

서버와 클라이언트의 소스 파일을 컴파일한 뒤 실행해봅니다. 먼저 콘솔(터미널)에서 GOPATH/src/tcpserver 디렉터리로 이동한 뒤 서버를 실행합니다(Windows에서는 명령 프롬프트 또는 PowerShell을 실행합니다). 저는 GOPATH를 /home/pyrasis/hello_project로 설정하였습니다.

~$ cd $GOPATH/src/tcpserver
~/hello_project/src/tcpserver$ ./tcpserver

서버를 실행했으면 콘솔에서 GOPATH/src/tcpclient 디렉터리로 이동한 뒤 클라이언트를 실행합니다.

~$ cd $GOPATH/src/tcpclient
~/hello_project/src/tcpclient$ ./tcpclient
Hello 0
Hello 1
Hello 2
Hello 3
... (생략)

클라이언트를 실행하면 Hello 숫자가 1초마다 출력됩니다. 마찬가지로 서버쪽 콘솔에서도 똑같이 출력됩니다.

Hello 0
Hello 1
Hello 2
Hello 3
... (생략)

이처럼 Go 언어에서는 TCP 서버를 간단하게 작성할 수 있습니다. 좀 더 자세한 예제는 ‘Unit 67 실전 예제: 채팅 서버 작성하기’를 참조하기 바랍니다.


저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

01 June 2015