RPC 프로토콜 사용하기

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

클라이언트 작성하기

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

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

  • func Dial(network, address string) (*Client, error): 프로토콜, IP 주소, 포트 번호를 설정하여 RPC 서버에 연결
  • func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error: RPC 서버의 함수를 호출(동기)
  • func (client *Client) Go(serviceMethod string, args interface{}, reply interface{}, done chan *Call) *Call: RPC 서버의 함수를 고루틴으로 호출(비동기)

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

GOPATH/src/rpcclient/rpcclient.go

package main

import (
	"fmt"
	"net/rpc"
)

type Args struct { // 매개변수
	A, B int
}

type Reply struct { // 리턴값
	C int
}

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

	// 동기 호출
	args := &Args{1, 2}
	reply := new(Reply)
	err = client.Call("Calc.Sum", args, reply) // Calc.Sum 함수 호출
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(reply.C)

	// 비동기 호출
	args.A = 4
	args.B = 9
	sumCall := client.Go("Calc.Sum", args, reply, nil) // Calc.Sum 함수를 고루틴으로 호출
	<-sumCall.Done // 함수가 끝날 때까지 대기
	fmt.Println(reply.C)
}

RPC 서버의 함수를 호출할 때 사용할 매개변수와 리턴값 구조체를 정의합니다. 이 부분은 서버와 동일하게 작성해야 하며 서버와 공유하는 패키지로 만들면 편리합니다.

type Args struct { // 매개변수
	A, B int
}

type Reply struct { // 리턴값
	C int
}

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

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

이제 서버의 Sum 함수를 실행합니다.

// 동기 호출
args := &Args{1, 2}
reply := new(Reply)
err = client.Call("Calc.Sum", args, reply) // Calc.Sum 함수 호출
if err != nil {
	fmt.Println(err)
	return
}
fmt.Println(reply.C)

매개변수 구조체 args를 채워넣고, 리턴값을 담을 reply도 메모리를 할당합니다. 그리고 client.Call 함수에 실행할 함수 이름, args, reply를 넣어줍니다. 서버에서 Sum 함수를 작성할 때 Calc 타입에 Sum 메서드로 만들었으므로 함수 이름은 Calc.Sum이 됩니다. client.Call 함수가 성공하면 reply에 결괏값이 저장됩니다.

이번에는 비동기로 서버의 Sum 함수를 실행하는 방법입니다.

// 비동기 호출
args.A = 4
args.B = 9
sumCall := client.Go("Calc.Sum", args, reply, nil) // Calc.Sum 함수를 고루틴으로 호출
<-sumCall.Done // 함수가 끝날 때까지 대기
fmt.Println(reply.C)

client.Go 함수에 실행할 함수 이름, args, reply를 넣어주면 rpc.Call 인스턴스가 리턴됩니다. 마지막 매개변수는 함수 실행이 끝났는지 확인하기 위한 채널입니다. 여기에 nil을 넣으면 채널이 새로 할당되어 리턴됩니다.

마지막으로 <-sumCall.Done처럼 Done 채널에 값이 들어올 때까지 기다리면 됩니다.

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

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

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

~$ cd $GOPATH/src/rpcclient
~/hello_project/src/rpcclient$ ./rpcclient
3
13

클라이언트를 실행하면 1과 2를 더한 값 3 그리고 4와 9를 더한 값 13이 출력됩니다.


저작권 안내

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

Published

01 June 2015