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网络编程
参考:net/rpc——Server/Client之间通信的秘密
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)
}