Format and remove 08.4.md spaces

This commit is contained in:
vCaesar
2017-06-10 12:16:14 +08:00
parent 6955edb1c4
commit be43d55cc1

View File

@@ -47,50 +47,50 @@ http的服务端代码实现如下
```Go ```Go
package main package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"net/rpc" "net/rpc"
) )
type Args struct { type Args struct {
A, B int A, B int
}
type Quotient struct {
Quo, Rem int
}
type Arith int
func (t *Arith) Multiply(args *Args, reply *int) error {
*reply = args.A * args.B
return nil
}
func (t *Arith) Divide(args *Args, quo *Quotient) error {
if args.B == 0 {
return errors.New("divide by zero")
} }
quo.Quo = args.A / args.B
quo.Rem = args.A % args.B
return nil
}
type Quotient struct { func main() {
Quo, Rem int
} arith := new(Arith)
rpc.Register(arith)
type Arith int rpc.HandleHTTP()
func (t *Arith) Multiply(args *Args, reply *int) error { err := http.ListenAndServe(":1234", nil)
*reply = args.A * args.B if err != nil {
return nil fmt.Println(err.Error())
}
func (t *Arith) Divide(args *Args, quo *Quotient) error {
if args.B == 0 {
return errors.New("divide by zero")
}
quo.Quo = args.A / args.B
quo.Rem = args.A % args.B
return nil
}
func main() {
arith := new(Arith)
rpc.Register(arith)
rpc.HandleHTTP()
err := http.ListenAndServe(":1234", nil)
if err != nil {
fmt.Println(err.Error())
}
} }
}
``` ```
通过上面的例子可以看到我们注册了一个Arith的RPC服务然后通过`rpc.HandleHTTP`函数把该服务注册到了HTTP协议上然后我们就可以利用http的方式来传递数据了。 通过上面的例子可以看到我们注册了一个Arith的RPC服务然后通过`rpc.HandleHTTP`函数把该服务注册到了HTTP协议上然后我们就可以利用http的方式来传递数据了。
@@ -99,59 +99,59 @@ http的服务端代码实现如下
```Go ```Go
package main package main
import ( import (
"fmt" "fmt"
"log" "log"
"net/rpc" "net/rpc"
"os" "os"
) )
type Args struct { type Args struct {
A, B int A, B int
}
type Quotient struct {
Quo, Rem int
}
func main() {
if len(os.Args) != 2 {
fmt.Println("Usage: ", os.Args[0], "server")
os.Exit(1)
} }
serverAddress := os.Args[1]
type Quotient struct { client, err := rpc.DialHTTP("tcp", serverAddress+":1234")
Quo, Rem int if err != nil {
log.Fatal("dialing:", err)
} }
// Synchronous call
func main() { args := Args{17, 8}
if len(os.Args) != 2 { var reply int
fmt.Println("Usage: ", os.Args[0], "server") err = client.Call("Arith.Multiply", args, &reply)
os.Exit(1) if err != nil {
} log.Fatal("arith error:", err)
serverAddress := os.Args[1]
client, err := rpc.DialHTTP("tcp", serverAddress+":1234")
if err != nil {
log.Fatal("dialing:", err)
}
// Synchronous call
args := Args{17, 8}
var reply int
err = client.Call("Arith.Multiply", args, &reply)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)
var quot Quotient
err = client.Call("Arith.Divide", args, &quot)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)
} }
fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)
var quot Quotient
err = client.Call("Arith.Divide", args, &quot)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)
}
``` ```
我们把上面的服务端和客户端的代码分别编译,然后先把服务端开启,然后开启客户端,输入代码,就会输出如下信息: 我们把上面的服务端和客户端的代码分别编译,然后先把服务端开启,然后开启客户端,输入代码,就会输出如下信息:
```Go ```Go
$ ./http_c localhost $ ./http_c localhost
Arith: 17*8=136 Arith: 17*8=136
Arith: 17/8=2 remainder 1 Arith: 17/8=2 remainder 1
``` ```
通过上面的调用可以看到参数和返回值是我们定义的struct类型在服务端我们把它们当做调用函数的参数的类型在客户端作为`client.Call`的第23两个参数的类型。客户端最重要的就是这个Call函数它有3个参数第1个要调用的函数的名字第2个是要传递的参数第3个要返回的参数(注意是指针类型)通过上面的代码例子我们可以发现使用Go的RPC实现相当的简单方便。 通过上面的调用可以看到参数和返回值是我们定义的struct类型在服务端我们把它们当做调用函数的参数的类型在客户端作为`client.Call`的第23两个参数的类型。客户端最重要的就是这个Call函数它有3个参数第1个要调用的函数的名字第2个是要传递的参数第3个要返回的参数(注意是指针类型)通过上面的代码例子我们可以发现使用Go的RPC实现相当的简单方便。
@@ -159,68 +159,68 @@ http的服务端代码实现如下
上面我们实现了基于HTTP协议的RPC接下来我们要实现基于TCP协议的RPC服务端的实现代码如下所示 上面我们实现了基于HTTP协议的RPC接下来我们要实现基于TCP协议的RPC服务端的实现代码如下所示
```Go ```Go
package main package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/rpc" "net/rpc"
"os" "os"
) )
type Args struct { type Args struct {
A, B int A, B int
}
type Quotient struct {
Quo, Rem int
}
type Arith int
func (t *Arith) Multiply(args *Args, reply *int) error {
*reply = args.A * args.B
return nil
}
func (t *Arith) Divide(args *Args, quo *Quotient) error {
if args.B == 0 {
return errors.New("divide by zero")
} }
quo.Quo = args.A / args.B
quo.Rem = args.A % args.B
return nil
}
type Quotient struct { func main() {
Quo, Rem int
}
type Arith int arith := new(Arith)
rpc.Register(arith)
func (t *Arith) Multiply(args *Args, reply *int) error { tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234")
*reply = args.A * args.B checkError(err)
return nil
}
func (t *Arith) Divide(args *Args, quo *Quotient) error { listener, err := net.ListenTCP("tcp", tcpAddr)
if args.B == 0 { checkError(err)
return errors.New("divide by zero")
}
quo.Quo = args.A / args.B
quo.Rem = args.A % args.B
return nil
}
func main() { for {
conn, err := listener.Accept()
arith := new(Arith)
rpc.Register(arith)
tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234")
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
for {
conn, err := listener.Accept()
if err != nil {
continue
}
rpc.ServeConn(conn)
}
}
func checkError(err error) {
if err != nil { if err != nil {
fmt.Println("Fatal error ", err.Error()) continue
os.Exit(1)
} }
rpc.ServeConn(conn)
} }
}
func checkError(err error) {
if err != nil {
fmt.Println("Fatal error ", err.Error())
os.Exit(1)
}
}
``` ```
上面这个代码和http的服务器相比不同在于:在此处我们采用了TCP协议然后需要自己控制连接当有客户端连接上来后我们需要把这个连接交给rpc来处理。 上面这个代码和http的服务器相比不同在于:在此处我们采用了TCP协议然后需要自己控制连接当有客户端连接上来后我们需要把这个连接交给rpc来处理。
@@ -229,51 +229,51 @@ http的服务端代码实现如下
```Go ```Go
package main package main
import ( import (
"fmt" "fmt"
"log" "log"
"net/rpc" "net/rpc"
"os" "os"
) )
type Args struct { type Args struct {
A, B int A, B int
}
type Quotient struct {
Quo, Rem int
}
func main() {
if len(os.Args) != 2 {
fmt.Println("Usage: ", os.Args[0], "server:port")
os.Exit(1)
} }
service := os.Args[1]
type Quotient struct { client, err := rpc.Dial("tcp", service)
Quo, Rem int if err != nil {
log.Fatal("dialing:", err)
} }
// Synchronous call
func main() { args := Args{17, 8}
if len(os.Args) != 2 { var reply int
fmt.Println("Usage: ", os.Args[0], "server:port") err = client.Call("Arith.Multiply", args, &reply)
os.Exit(1) if err != nil {
} log.Fatal("arith error:", err)
service := os.Args[1]
client, err := rpc.Dial("tcp", service)
if err != nil {
log.Fatal("dialing:", err)
}
// Synchronous call
args := Args{17, 8}
var reply int
err = client.Call("Arith.Multiply", args, &reply)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)
var quot Quotient
err = client.Call("Arith.Divide", args, &quot)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)
} }
fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)
var quot Quotient
err = client.Call("Arith.Divide", args, &quot)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)
}
``` ```
这个客户端代码和http的客户端代码对比唯一的区别一个是DialHTTP一个是Dial(tcp),其他处理一模一样。 这个客户端代码和http的客户端代码对比唯一的区别一个是DialHTTP一个是Dial(tcp),其他处理一模一样。
@@ -283,121 +283,121 @@ JSON RPC是数据编码采用了JSON而不是gob编码其他和上面介
```Go ```Go
package main package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"net" "net"
"net/rpc" "net/rpc"
"net/rpc/jsonrpc" "net/rpc/jsonrpc"
"os" "os"
) )
type Args struct { type Args struct {
A, B int A, B int
}
type Quotient struct {
Quo, Rem int
}
type Arith int
func (t *Arith) Multiply(args *Args, reply *int) error {
*reply = args.A * args.B
return nil
}
func (t *Arith) Divide(args *Args, quo *Quotient) error {
if args.B == 0 {
return errors.New("divide by zero")
} }
quo.Quo = args.A / args.B
quo.Rem = args.A % args.B
return nil
}
type Quotient struct { func main() {
Quo, Rem int
}
type Arith int arith := new(Arith)
rpc.Register(arith)
func (t *Arith) Multiply(args *Args, reply *int) error { tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234")
*reply = args.A * args.B checkError(err)
return nil
}
func (t *Arith) Divide(args *Args, quo *Quotient) error { listener, err := net.ListenTCP("tcp", tcpAddr)
if args.B == 0 { checkError(err)
return errors.New("divide by zero")
}
quo.Quo = args.A / args.B
quo.Rem = args.A % args.B
return nil
}
func main() { for {
conn, err := listener.Accept()
arith := new(Arith)
rpc.Register(arith)
tcpAddr, err := net.ResolveTCPAddr("tcp", ":1234")
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
for {
conn, err := listener.Accept()
if err != nil {
continue
}
jsonrpc.ServeConn(conn)
}
}
func checkError(err error) {
if err != nil { if err != nil {
fmt.Println("Fatal error ", err.Error()) continue
os.Exit(1)
} }
jsonrpc.ServeConn(conn)
} }
}
func checkError(err error) {
if err != nil {
fmt.Println("Fatal error ", err.Error())
os.Exit(1)
}
}
``` ```
通过示例我们可以看出 json-rpc是基于TCP协议实现的目前它还不支持HTTP方式。 通过示例我们可以看出 json-rpc是基于TCP协议实现的目前它还不支持HTTP方式。
请看客户端的实现代码: 请看客户端的实现代码:
```Go ```Go
package main package main
import ( import (
"fmt" "fmt"
"log" "log"
"net/rpc/jsonrpc" "net/rpc/jsonrpc"
"os" "os"
) )
type Args struct { type Args struct {
A, B int A, B int
}
type Quotient struct {
Quo, Rem int
}
func main() {
if len(os.Args) != 2 {
fmt.Println("Usage: ", os.Args[0], "server:port")
log.Fatal(1)
} }
service := os.Args[1]
type Quotient struct { client, err := jsonrpc.Dial("tcp", service)
Quo, Rem int if err != nil {
log.Fatal("dialing:", err)
} }
// Synchronous call
func main() { args := Args{17, 8}
if len(os.Args) != 2 { var reply int
fmt.Println("Usage: ", os.Args[0], "server:port") err = client.Call("Arith.Multiply", args, &reply)
log.Fatal(1) if err != nil {
} log.Fatal("arith error:", err)
service := os.Args[1]
client, err := jsonrpc.Dial("tcp", service)
if err != nil {
log.Fatal("dialing:", err)
}
// Synchronous call
args := Args{17, 8}
var reply int
err = client.Call("Arith.Multiply", args, &reply)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)
var quot Quotient
err = client.Call("Arith.Divide", args, &quot)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)
} }
fmt.Printf("Arith: %d*%d=%d\n", args.A, args.B, reply)
var quot Quotient
err = client.Call("Arith.Divide", args, &quot)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d/%d=%d remainder %d\n", args.A, args.B, quot.Quo, quot.Rem)
}
``` ```
## 总结 ## 总结
Go已经提供了对RPC的良好支持通过上面HTTP、TCP、JSON RPC的实现,我们就可以很方便的开发很多分布式的Web应用我想作为读者的你已经领会到这一点。但遗憾的是目前Go尚未提供对SOAP RPC的支持欣慰的是现在已经有第三方的开源实现了。 Go已经提供了对RPC的良好支持通过上面HTTP、TCP、JSON RPC的实现,我们就可以很方便的开发很多分布式的Web应用我想作为读者的你已经领会到这一点。但遗憾的是目前Go尚未提供对SOAP RPC的支持欣慰的是现在已经有第三方的开源实现了。