golang 的net包的網路程式設計 TCP | HTTP | RPC
阿新 • • 發佈:2022-05-18
目錄
golang net包
golang net包
1.TCP網路程式設計
server.go
package main import ( "fmt" "log" "net" "os" "time" ) func main() { // 建立socket監聽 lis, err := net.Listen("tcp", "localhost:1024") log.Println("server up at " + lis.Addr().String()) defer lis.Close() log.Println("Waiting for clients...") // 處理錯誤 if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) } // 處理客戶端連線 for { conn, err := lis.Accept() if err != nil { continue } log.Printf("client addr: %s, tcp connect success", conn.RemoteAddr()) go handle(conn) } } func handle(conn net.Conn) { buffer := make([]byte, 2048) // 迴圈讀取客戶請求 for { n, err := conn.Read(buffer) if err != nil { log.Printf("%s connection error: %s", conn.RemoteAddr(), err) return } log.Printf("From %s receive data string: %s\n", conn.RemoteAddr(), string(buffer[:n])) // 收到的返回資訊 strTmp := fmt.Sprintf("server got msg \"%s\" at %s", string(buffer[:n]), time.Now().String()) conn.Write([]byte(strTmp)) } }
client.go
package main import ( "bufio" "fmt" "log" "net" "os" ) func main() { addr := "127.0.0.1:1024" conn, err := net.Dial("tcp", addr) defer conn.Close() if err != nil { fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error()) os.Exit(1) } log.Printf("connection server: %s success", addr) sendLoop(conn) } func send(conn net.Conn) { words := "hello server!" conn.Write([]byte(words)) log.Println("send over") // receive from server buffer := make([]byte, 2048) n, err := conn.Read(buffer) if err != nil { log.Printf("%s waiting server back msg error: %s", conn.RemoteAddr(), err) return } log.Printf("%s receive server back msg: %s", conn.RemoteAddr(), string(buffer[:n])) } func sendLoop(conn net.Conn) { for { input, _ := bufio.NewReader(os.Stdin).ReadString('\n') _, err := conn.Write([]byte(input)) if err != nil { log.Println(err) } log.Println("send over") // receive from server buffer := make([]byte, 2048) n, err := conn.Read(buffer) if err != nil { log.Printf("%s waiting server back msg error: %s", conn.RemoteAddr(), err) return } log.Printf("%s receive server back msg: %s", conn.RemoteAddr(), string(buffer[:n])) } }
2.HTTP網路程式設計
2.1 HTTP
server.go
package main import ( "fmt" "log" "net/http" ) func main() { // register callback func http.HandleFunc("/index", indexHandle) log.Println("HTTP server up at", "http://localhost:8080") // bind ip and start recv req err := http.ListenAndServe(":8080", nil) if err != nil { log.Fatal("ListenAndServe:", err) } } func indexHandle(w http.ResponseWriter, r *http.Request) { fmt.Println("method = ", r.Method) //請求方法 fmt.Println("URL = ", r.URL) // 瀏覽器傳送請求檔案路徑 fmt.Println("header = ", r.Header) // 請求頭 fmt.Println("body = ", r.Body) // 請求包體 fmt.Println(r.RemoteAddr, "連線成功") //客戶端網路地址 w.Write([]byte("Hello from http server")) //fmt.Fprint(w, "Hello from http server") }
client.go
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func main() {
resp, err := http.Get("http://localhost:8080/index")
if err != nil {
log.Println("Get err:", err)
return
}
defer resp.Body.Close()
// parse resp data
// 獲取伺服器端讀到的資料---header
fmt.Println("Status = ", resp.Status) // 狀態
fmt.Println("StatusCode = ", resp.StatusCode) // 狀態碼
fmt.Println("Header = ", resp.Header) // 響應頭部
fmt.Println("Body = ", resp.Body) // 響應包體
// resp body
content, err := ioutil.ReadAll(resp.Body)
log.Println("response body:", string(content))
}
2.2 HTTPS
server.go
package main
import (
"fmt"
"log"
"net/http"
)
func main() {
http.HandleFunc("/index", indexHandle)
log.Println("HTTPS server up at https://localhost:8443")
http.ListenAndServeTLS(":8443", "D:\\demo1\\src\\demo\\demo05\\https-server\\server\\server.crt",
"D:\\demo1\\src\\demo\\demo05\\https-server\\server\\server.key", nil)
}
func indexHandle(w http.ResponseWriter, r *http.Request) {
log.Println(r.RemoteAddr, r.URL, r.Proto, r.Header, r.Body)
fmt.Fprint(w, "Hi, This is an example of https service in golang!")
}
client.go
package main
import (
"crypto/tls"
"crypto/x509"
"io/ioutil"
"log"
"net/http"
)
func main() {
// create cert pool, which stands for cert set
pool := x509.NewCertPool()
caCrtPath := "D:\\demo1\\src\\demo\\demo05\\https-server\\client\\ca.crt"
// call ca.crt
caCrt, err := ioutil.ReadFile(caCrtPath)
if err != nil {
log.Println("ReadFile err:", err)
return
}
// parse cert
pool.AppendCertsFromPEM(caCrt)
tr := &http.Transport{
// InsecureSkipVerify-如果設定為true, 則不會校驗證書以及證書中的主機名和伺服器主機名是否一致
TLSClientConfig: &tls.Config{RootCAs: pool, InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://localhost:8443/index")
if err != nil {
log.Println("Get err:", err)
return
}
defer resp.Body.Close()
content, err := ioutil.ReadAll(resp.Body)
log.Println(string(content))
}
3.RPC網路程式設計
3.1 基於TCP的RPC
server.go
client.go
3.2 基於HTTP的RPC
server.go
package main
import (
"fmt"
"log"
"net/http"
"net/rpc"
)
type Student struct {
Name string
School string
}
type RpcServer struct {}
func (r *RpcServer) Introduce(student Student, words *string) error {
log.Println("student:", student)
*words = fmt.Sprintf("Hello everyone, my name is %s, and I am from %s", student.Name, student.School)
return nil
}
func main() {
rpcServer := new(RpcServer)
// register rpc service
_ = rpc.Register(rpcServer)
// service bind to http protocol
rpc.HandleHTTP()
log.Println("http rpc service start success addr:8080")
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal(err)
}
}
client.go
package main
import (
"log"
"net/rpc"
)
func main() {
type Student struct {
Name string
School string
}
// connect rpc server
client, err := rpc.DialHTTP("tcp", "127.0.0.1:8080")
if err != nil {
panic(err)
}
defer client.Close()
// send request
var reply string
err = client.Call("RpcServer.Introduce", &Student{Name: "random_w", School: "Secret"}, &reply)
if err != nil {
panic(nil)
}
log.Println(reply)
}
3.3 基於jsonRpc的RPC
server.go
package main
import (
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
)
type Student struct {
Name string
School string
}
type RpcServer struct{}
func (r *RpcServer) Introduce(student Student, words *string) error {
log.Println("student: ", student)
*words = fmt.Sprintf("Hello everyone, my name is %s, and I am from %s", student.Name, student.School)
return nil
}
func main() {
rpcServer := new(RpcServer)
// register rpc service
_ = rpc.Register(rpcServer)
// json-rpc based on tcp protocol, not http
tcpLis, err := net.Listen("tcp", "127.0.0.1:8080")
if err != nil {
panic(err)
}
log.Println("tcp json-rpc service start success addr:8080")
for {
// listen request from clients
conn, err := tcpLis.Accept()
if err != nil {
continue
}
go jsonrpc.ServeConn(conn)
}
}
client.go
package main
import (
"log"
"net/rpc/jsonrpc"
)
func main() {
type Student struct {
Name string
School string
}
client, err := jsonrpc.Dial("tcp", "127.0.0.1:8080")
if err != nil {
panic(err)
}
defer client.Close()
var reply string
err = client.Call("RpcServer.Introduce", &Student{
Name: "random_w",
School: "Secret",
}, &reply)
if err != nil {
panic(err)
}
log.Println(reply)
}