使用Go实现Socket服务端和客户端通信
生活随笔
收集整理的這篇文章主要介紹了
使用Go实现Socket服务端和客户端通信
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
代碼下載:Golangsocketserver-C#文檔類資源-CSDN下載
1、目錄結(jié)構(gòu)如下:
2、main入口調(diào)用:main.go
package mainimport ("fmt""socket_server/server" )func main() {(&server.SocketServer{Network: "tcp4",Address: "127.0.0.1:8879",Clients: make(map[string]*server.TcpConn),ClientTimeOutSecond: 5,MaxClientNum: 2,OnError: func(msg string, err error) {fmt.Println(msg, err)},OnStart: func(server *server.SocketServer) {fmt.Println("啟動(dòng)OK")},OnClientConnect: func(client *server.TcpConn) {fmt.Println("客戶端連接成功:", client.Id)},OnClientClose: func(client *server.TcpConn) {fmt.Println("客戶端連接關(guān)閉:", client.Id)},OnMessage: func(client *server.TcpConn, msg string) {fmt.Println("接收數(shù)據(jù):", msg)client.Connect.Write([]byte("服務(wù)端接收到了你的消息:" + msg + "&&&&"))},}).Start() }?3、socket主服務(wù):SocketServer.go
package serverimport ("fmt""net""sync""time" )//socket主服務(wù) type SocketServer struct {Network stringAddress string //監(jiān)聽ip和端口,例如:127.0.0.1:8000Clients map[string]*TcpConn //客戶端列表ClientTimeOutSecond int64 //客戶端超時(shí)時(shí)間,N秒沒有收到客戶端消息就關(guān)閉MaxClientNum int //客戶端最大連接數(shù)CurrentClientNum int //當(dāng)然客戶端連接數(shù)量OnError func(msg string, err error) //發(fā)生錯(cuò)誤OnStart func(server *SocketServer) //socket啟動(dòng)OnClientConnect func(client *TcpConn) //客戶端連接上OnClientClose func(client *TcpConn) //與客戶端關(guān)閉連接OnMessage func(client *TcpConn, msg string) //接收到客戶端消息 }//啟動(dòng)socket func (server *SocketServer) Start() {listener, err := net.Listen(server.Network, server.Address)if err != nil {server.OnError("Listen失敗", err)return}defer listener.Close()fmt.Printf("socket 啟動(dòng)成功;Network=%s,Address=%s", server.Network, server.Address)server.OnStart(server)go server.CheckClient()for true {conn, err := listener.Accept()if err != nil {server.OnError("Accept失敗", err)continue}if server.CurrentClientNum >= server.MaxClientNum {fmt.Println("已經(jīng)達(dá)到最大連接數(shù)了:", server.CurrentClientNum)conn.Close()continue}client := MakeClient(conn, server)server.OnClientConnect(client)server.AddClient(client)go client.HandleMessage()} }var mutex sync.Mutexfunc (server *SocketServer) AddClient(client *TcpConn) {mutex.Lock()defer mutex.Unlock()server.Clients[client.Id] = clientserver.CurrentClientNum++fmt.Println("新增連接,連接數(shù):", server.CurrentClientNum) }func (server *SocketServer) RemoveClient(client *TcpConn) {mutex.Lock()defer mutex.Unlock()if _, ok := server.Clients[client.Id]; ok {client.Connect.Close()delete(server.Clients, client.Id)server.OnClientClose(client)server.CurrentClientNum--fmt.Println("移除連接,連接數(shù):", server.CurrentClientNum)} }//檢查超時(shí) func (server *SocketServer) CheckClient() {for true {if server.ClientTimeOutSecond < 1 {time.Sleep(5 * time.Second)continue}mutex.Lock()nowTime := time.Now().Unix()for key, value := range server.Clients {if nowTime-value.LastTime > server.ClientTimeOutSecond {value.Connect.Close()fmt.Println("移除超時(shí)客戶端:", key, len(server.Clients))}}mutex.Unlock()time.Sleep(5 * time.Second)} }4、客戶端連接對(duì)象:TcpConn
package serverimport ("net""strings""time" )//客戶端連接,一個(gè)連接一個(gè)TcpConn type TcpConn struct {Id string //客戶端唯一標(biāo)識(shí)Connect net.Conn //客戶端連接對(duì)象Server *SocketServerLastTime int64 //最后通訊時(shí)間 }//創(chuàng)建連接客戶端 func MakeClient(connnect net.Conn, server *SocketServer) *TcpConn {client := &TcpConn{Id: connnect.RemoteAddr().String(),Connect: connnect,Server: server,LastTime: time.Now().Unix(),}return client }//接收數(shù)據(jù) func (conn *TcpConn) HandleMessage() {var buffer [1024]byte //測(cè)試用8,真實(shí)環(huán)境用多少一點(diǎn)msg := ""for true {readcount, err := conn.Connect.Read(buffer[:])if err != nil {conn.Server.RemoveClient(conn)conn.Server.OnError("讀取數(shù)據(jù)錯(cuò)誤,關(guān)閉連接:", err)break}if readcount == 0 {conn.Server.OnError("讀取數(shù)據(jù)失敗:"+string(readcount), nil)continue}conn.LastTime = time.Now().Unix()msg += string(buffer[:readcount])//fmt.Println("msg1:", msg)if strings.Contains(msg, "&&&&") {msgs := strings.Split(msg, "&&&&") //"我是中國人&&&&哈哈哈哈&&&&"切出來的數(shù)組長度是3,將數(shù)組位置1和2的都是一條完整的數(shù)據(jù)if len(msgs) > 1 {for _, m := range msgs[0 : len(msgs)-1] {conn.Server.OnMessage(conn, m)}msg = msgs[len(msgs)-1]//fmt.Println("msg2:", msg)}}} }5、測(cè)試客戶端:SocketClient.go 和 main.go
package clientimport ("fmt""net""strings""sync" )type SocketClient struct {Network stringAddress string //監(jiān)聽ip和端口,例如:127.0.0.1:8000OnMessage func(msg string)Connect net.ConnWg sync.WaitGroup }func (client *SocketClient) Start() error {conn, err := net.Dial(client.Network, client.Address)if err != nil {return err}client.Wg.Add(1)go HandleMessage(conn, client)client.Connect = connreturn nil }//接收數(shù)據(jù) func HandleMessage(conn net.Conn, client *SocketClient) {var buffer [8]byte //測(cè)試用8,真實(shí)環(huán)境用多少一點(diǎn)msg := ""defer client.Wg.Done()for true {readcount, err := conn.Read(buffer[:])if err != nil || readcount == 0 {fmt.Println(err)break}msg += string(buffer[:readcount])if strings.Contains(msg, "&&&&") {msgs := strings.Split(msg, "&&&&") //"我是中國人&&&&哈哈哈哈&&&&"切出來的數(shù)組長度是3,將數(shù)組位置1和2的是一條數(shù)據(jù)if len(msgs) > 1 {for _, m := range msgs[0 : len(msgs)-1] {client.OnMessage(m)}msg = msgs[len(msgs)-1]}}} } package mainimport ("fmt""socket_client/client""time" )func main() {for true {var client = &client.SocketClient{Network: "tcp4",Address: "127.0.0.1:8879",OnMessage: func(msg string) {fmt.Println("接收到服務(wù)端的消息", msg)},}err := client.Start()if err != nil {fmt.Println("連接服務(wù)端失敗", err)return}//for true {client.Connect.Write([]byte("我是中國人&&&哈哈哈哈&&&&"))client.Connect.Write([]byte("I come from china&&&&are you?&&&&"))//time.Sleep(time.Second * 3)//}client.Wg.Wait()fmt.Println("與服務(wù)器連接斷開,3秒后重試")time.Sleep(time.Second * 3)} }6、運(yùn)行效果如下:
總結(jié)
以上是生活随笔為你收集整理的使用Go实现Socket服务端和客户端通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UVa 11636 Hello Worl
- 下一篇: [Socket]BSD socket简易