go网络编程
1. tcp
package netMode
import (
"fmt"
"net"
)
var (
protocol = "tcp"
addr = "localhost:9999"
)
func TcpServer() {
listener, err := net.Listen(protocol, addr)
defer listener.Close()
if err != nil {
fmt.Println("listen error:", err)
return
}
for {
con, err := listener.Accept()
if err != nil {
fmt.Println("accept error:", err)
continue
}
go func(con net.Conn) {
defer con.Close()
data := make([]byte, 1024)
n, err := con.Read(data)
if err != nil {
fmt.Println("server-read error:", err)
return
}
recvData := string(data[:n])
fmt.Println("server-read data:", recvData)
n, err = con.Write([]byte(recvData))
if err != nil {
fmt.Println("server-write error:", err)
return
}
fmt.Println("server-write data:", string(data[:n]))
}(con)
}
}
func TcpClient() {
dial, err := net.Dial(protocol, addr)
if err != nil {
fmt.Println("dail error:", err)
return
}
defer dial.Close()
buf := make([]byte, 1024)
sendData := []byte("hello tcp")
n, err := dial.Write(sendData)
if err != nil {
fmt.Println("client-write error:", err)
return
}
fmt.Println("client-write data:", string(sendData))
n, err = dial.Read(buf)
if err != nil {
fmt.Println("client-read error:", err)
return
}
fmt.Println("client-read data:", string(buf[:n]))
}
serverOut:
server-read data: hello tcp
server-write data: hello tcp
clientOut:
client-write data: hello tcp
client-read data: hello tcp
2. udp
package netMode
import (
"fmt"
"net"
)
func UdpServer() {
listener, err := net.ListenUDP("udp", &net.UDPAddr{
net.IPv4(0, 0, 0, 0),
9999,
"",
})
defer listener.Close()
if err != nil {
fmt.Println("listen error:", err)
return
}
for {
buf := make([]byte, 1024)
n, udpAddr, err := listener.ReadFromUDP(buf)
if err != nil {
fmt.Println("server-read error:", err)
continue
}
fmt.Printf("server-read(client:%s) data:%s\n", udpAddr, string(buf[:n]))
sendData := []byte(udpAddr.String())
n, err = listener.WriteToUDP(sendData, udpAddr)
if err != nil {
fmt.Println("server-write error:", err)
continue
}
fmt.Println("server-write data:", string(sendData))
}
}
func UdpClient() {
udpAddr, err := net.ResolveUDPAddr("", ":9999")
if err != nil {
fmt.Println("client-resolve error:", err)
return
}
con, err := net.DialUDP("udp", nil, udpAddr)
if err != nil {
fmt.Println("client-dial error:", err)
return
}
defer con.Close()
sendData := []byte("hello udp")
_, err = con.Write(sendData)
if err != nil {
fmt.Println("client-write error:", err)
return
}
fmt.Println("client-write:", string(sendData))
buf := make([]byte, 1024)
n, addr, err := con.ReadFromUDP(buf)
if err != nil {
fmt.Printf("clien-read(server:%s) error: %s\n", addr, err.Error())
return
}
fmt.Printf("client-read(server:%s) data:%s\n", addr, string(buf[:n]))
}
func UdpBroadCastServer() {
serverAddr, err := net.ResolveUDPAddr("udp4", ":9999")
if err != nil {
fmt.Println("server-resolve error:", err)
return
}
udp, err := net.ListenUDP("udp4", serverAddr)
if err != nil {
fmt.Println("server-listen error:", err)
return
}
broadCastAddr, err := net.ResolveUDPAddr("udp4", "255.255.255.255:9999")
if err != nil {
fmt.Println("server-resolve-broadCast error:", err)
return
}
for {
send := []byte("hello broadcast")
_, err := udp.WriteToUDP(send, broadCastAddr)
if err != nil {
fmt.Println("server-write error:", err)
return
}
fmt.Println("server-broadcast data:", string(send))
}
}
func UdpBroadCastClient(serverAddr *net.UDPAddr) {
udpAddr, err := net.ResolveUDPAddr("udp4", ":9999")
if err != nil {
fmt.Println("client-resolve error:", err)
return
}
udp, err := net.DialUDP("udp4", udpAddr, serverAddr)
if err != nil {
fmt.Println("client-dial error:", err)
return
}
buf := make([]byte, 1024)
n, addr, err := udp.ReadFromUDP(buf)
if err != nil {
fmt.Println("client-read error:", err)
return
}
fmt.Printf("client-read(server:%s) data:%s\n", addr, string(buf[:n]))
}
serverOut:
server-read(client:127.0.0.1:63379) data:hello udp
server-write-broadcast data: 127.0.0.1:63379
clientOut:
client-write: hello udp
client-read(server:127.0.0.1:9999) data:127.0.0.1:63379
3. http
package netMode
import (
"fmt"
"io"
"net/http"
)
func HttpServer() {
http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
fmt.Println("请求信息====>")
fmt.Println("addr:", r.RemoteAddr)
fmt.Println("method:", r.Method)
fmt.Println("url:", r.URL.Path)
fmt.Println("header:", r.Header)
fmt.Println("body:", r.Body)
fmt.Println("响应====>")
w.Write([]byte("ok"))
})
http.ListenAndServe(":9999", nil)
}
func HttpClient() {
resp, err := http.Get("http://localhost:9999/test")
if err != nil {
fmt.Println("error:", err)
}
defer resp.Body.Close()
buffer := make([]byte, 1024)
for {
n, err := resp.Body.Read(buffer)
if err != nil && err != io.EOF {
fmt.Println("error:", err)
break
} else {
fmt.Println("data:", string(buffer[:n]))
break
}
}
}
serverOut:
请求信息====>
addr: 127.0.0.1:52995
method: GET
url: /test
header: map[Accept-Encoding:[gzip] User-Agent:[Go-http-client/1.1]]
body: {}
响应====>
clientOut:
data: ok
4. websocket
go get -u github.com/gorilla/websocket
package netMode
import (
"fmt"
"github.com/gorilla/websocket"
"net/http"
)
func WebSocketServer() {
upgrader := websocket.Upgrader{
HandshakeTimeout: 0,
ReadBufferSize: 1024,
WriteBufferSize: 1024,
WriteBufferPool: nil,
Subprotocols: nil,
Error: nil,
CheckOrigin: func(r *http.Request) bool {
return true
},
EnableCompression: false,
}
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
con, err := upgrader.Upgrade(w, r, nil)
if err != nil {
fmt.Println("websocket-upgrade-error:", err)
return
}
defer con.Close()
sendData := []byte("server-websocket")
err = con.WriteMessage(websocket.TextMessage, sendData)
if err != nil {
fmt.Println("server-write-error:", err)
return
}
fmt.Println("server-write-data:", string(sendData))
messageType, p, err := con.ReadMessage()
if err != nil {
fmt.Println("server-read-error:", err)
return
}
fmt.Println("server-read-data:", string(p), messageType)
})
http.ListenAndServe(":9999", nil)
}
func WebSocketClient() {
dial, _, err := websocket.DefaultDialer.Dial("ws://localhost:9999/ws", nil)
if err != nil {
fmt.Println("client-connect-error:", err)
return
}
defer dial.Close()
sendData := []byte("client-websocket")
err = dial.WriteMessage(1, sendData)
if err != nil {
fmt.Println("client-write-error:", err)
return
}
fmt.Println("client-write-data:", string(sendData))
messageType, p, err := dial.ReadMessage()
if err != nil {
fmt.Println("client-read-error:", err)
return
}
fmt.Println("client-read-data:", string(p), messageType)
}
serverOut:
server-write-data: server-websocket
server-read-data: client-websocket 1
clientOut:
client-write-data: client-websocket
client-read-data: server-websocket 1
5. rpc
https://books.studygolang.com/go-rpc-programming-guide/part1/gorpc.html
package netMode
import (
"fmt"
"net"
"net/http"
"net/rpc"
)
type Args struct {
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 {
quo.Quo = args.A + args.B
quo.Rem = args.A - args.B
return nil
}
func RpcServer() {
arith := new(Arith)
rpc.Register(arith)
rpc.HandleHTTP()
listen, err := net.Listen("tcp", ":9999")
if err != nil {
fmt.Println("listen error:", err)
return
}
go http.Serve(listen, nil)
select {}
}
func RpcClient() {
dial, err := rpc.DialHTTP("tcp", ":9999")
if err != nil {
fmt.Println("client-connect-error:", err)
return
}
defer dial.Close()
args := Args{10, 11}
var reply int
err = dial.Call("Arith.Multiply", args, &reply)
if err != nil {
fmt.Println("client-sync-call-error:", err)
return
}
fmt.Printf("client-sync-call-data(%d*%d):%d\n", args.A, args.B, reply)
quotient := new(Quotient)
call := dial.Go("Arith.Divide", args, quotient, nil)
fmt.Println("client-async-call-method:", call.ServiceMethod)
fmt.Println("client-async-call-args:", call.Args)
fmt.Println("client-async-call-done:", <-call.Done)
fmt.Println("client-async-call-reply:", call.Reply)
}
clientOut:
client-call-data(10*11):110
call-method: Arith.Divide
call-args: {10 11}
call-done: &{Arith.Divide {10 11} 0xc0001a2b80 <nil> 0xc000056540}
call-reply: &{21 -1}
6. grpc
1. grpc参考文档
https://www.topgoer.cn/docs/grpc/grpc-1d2ud3fh1d74h
2. 前置要求
2.1 go环境已添加到环境变量
2.2 protoc编译器下载
windows下载protoc-27.2-win64.zip、linux选择版本下载
https://github.com/protocolbuffers/protobuf/releases
2.3 protobuf文件所需exe应用和grpc服务所需依赖
go get -u google.golang.org/grpc
go install google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
2.4 将下载的exe迁移到go环境/bin目录下
|----bin
|----bin/go.exe
|----bin/protoc.exe
|----bin/protc-gen-go.exe
|----bin/protoc-gen-go-grpc.exe
2.5 编写proto文件
2.6 命令生成当前开发语言适配的源码
protoc --go_out=. --go-grpc_out=. proto/test.proto
2.7 实例
|----netMode
|----netMode/grpcDemo.go
|----netMode/proto/test.proto
|----netMode/proto/test.pb.go
|----netMode/proto/test_grpc.pb.go
syntax="proto3";
package <包名>;
option go_package="包名";
message TestReq {
string per_name = 1;
int32 per_age = 2;
Status status = 3;
map<string,string> info = 4;
}
message TestRes {
string msg = 1;
string code = 2;
}
enum Status {
IS_OK = 0;
IS_FAIL = 1;
}
service MyService {
rpc Query (TestReq) returns (TestRes){}
}
protoc --go_out=. --go-grpc_out=. proto/test.proto
syntax="proto3";
option go_package = "/proto";
service TestService {
rpc Query (TestReq) returns (TestRes){}
}
message TestReq {
string name = 1;
int32 age = 2;
enum Sex {
male = 0;
female = 1;
}
Sex sex = 3;
repeated string score = 4;
}
message TestRes {
map<string, string> info = 1;
}
package netMode
import (
"context"
"fmt"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"net"
"strings"
pb "workProject/src/apps/netMode/proto"
)
type GrpcServer_ struct {
*pb.UnimplementedTestServiceServer
}
func (server *GrpcServer_) Query(ctx context.Context, req *pb.TestReq) (res *pb.TestRes, err error) {
fmt.Println("server-get-req:", req)
resMap := map[string]string{
"name": req.GetName(),
"age": string(req.GetAge()),
"sex": req.GetSex().String(),
"score": fmt.Sprintf(strings.Join(req.GetScore(), ",")),
}
res = &pb.TestRes{
Info: resMap,
}
return res, nil
}
func GrpcServer() {
listen, err := net.Listen("tcp", ":9999")
if err != nil {
fmt.Println("server-listen-error:", err)
return
}
server := grpc.NewServer()
pb.RegisterTestServiceServer(server, &GrpcServer_{})
defer func() {
server.Stop()
listen.Close()
}()
fmt.Println("server-listen:9999")
err = server.Serve(listen)
if err != nil {
fmt.Println("server-run-error:", err)
return
}
}
func GrpcClient() {
conn, err := grpc.NewClient(":9999", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
fmt.Println("client-connect-error:", err)
return
}
defer conn.Close()
client := pb.NewTestServiceClient(conn)
req := pb.TestReq{
Name: "张三",
Age: 18,
Sex: 0,
Score: []string{"10", "20", "30"},
}
query, err := client.Query(context.TODO(), &req)
if err != nil {
fmt.Println("client-req-error:", err)
return
}
fmt.Println("client-req-data:", query.GetInfo())
}
serverOut:
server-listen:9999
server-get-req: name:"张三" age:18 score:"10" score:"20" score:"30"
clientOut:
client-req-data: map[age: name:张三 score:10,20,30 sex:male]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下