从零开始写Go网络通信框架(4)——全双工收发消息
来源:互联网 发布:人工神经网络算法教程 编辑:程序博客网 时间:2024/06/06 04:43
经过上面三篇文章,我们已经写了一个简单的C/S框架,可以实现客户端与服务端进行发送消息。但这是一个单向通讯的。我们要想让客户端接收服务端发来的命令,并执行响应的动作,就需要写成全双工收发消息。即客户端也能接收服务端发来的指令。
下面我在客户端定义一个方法,用来接收服务端的消息。
//接收服务端发来的消息func ReadMsg(conn net.Conn) {//存储被截断的数据tmpbuf:=make([] byte,0)buf:=make([] byte,1024)//将信息解包n,_:=conn.Read(buf)tmpbuf = protocol.Depack(append(tmpbuf,buf[:n]...))msg:=string(tmpbuf)fmt.Println("server say:",msg)}
客户端完整代码如下:
package mainimport ("fmt""os""net""strconv""time""github.com/mxi4oyu/MoonSocket/protocol")//定义CheckError方法,避免写太多到 if err!=nilfunc CheckError(err error) {if err!=nil{fmt.Fprintf(os.Stderr,"Fatal error:%s",err.Error())os.Exit(1)}}func main() {if len(os.Args) !=2 {fmt.Fprintf(os.Stderr,"Usage:%s IP:Port\n",os.Args[0])os.Exit(1)}//动态传入服务端IP和端口号service:=os.Args[1]tcpAddr,err:=net.ResolveTCPAddr("tcp4",service)CheckError(err)conn,err:=net.DialTCP("tcp",nil,tcpAddr)CheckError(err)ch:=make(chan int,100)ticker := time.NewTicker(time.Second)defer ticker.Stop()for{select {case <-ticker.C:ch<-1go ClientMsgHandler(conn,ch)case <-time.After(time.Second*10):defer conn.Close()fmt.Println("timeout")}}}//客户端消息处理func ClientMsgHandler(conn net.Conn,ch chan int) {<-ch//获取当前时间msg:=time.Now().String()go SendMsg(conn,msg)go ReadMsg(conn)}func GetSession() string{gs1:=time.Now().Unix()gs2:=strconv.FormatInt(gs1,10)return gs2}//接收服务端发来的消息func ReadMsg(conn net.Conn) {//存储被截断的数据tmpbuf:=make([] byte,0)buf:=make([] byte,1024)//将信息解包n,_:=conn.Read(buf)tmpbuf = protocol.Depack(append(tmpbuf,buf[:n]...))msg:=string(tmpbuf)fmt.Println("server say:",msg)}//向服务端发送消息func SendMsg(conn net.Conn,msg string) {session:=GetSession()words := "{\"Session\":"+session +",\"Meta\":\"Monitor\",\"Message\":\""+msg+"\"}"//将信息封包smsg:=protocol.Enpack([]byte(words))conn.Write(smsg)}
在服务端,我们也做了响应的调整。定义一个方法,专门向客户端发送消息。
//服务端向客户端发送消息func WriteMsgToClient(conn net.Conn) {talk:="wordpress"//将信息封包smsg:=protocol.Enpack([]byte(talk))conn.Write(smsg)}
服务端完整代码如下:
package mainimport ("fmt""os""net""log""github.com/mxi4oyu/MoonSocket/protocol""time")//定义CheckError方法,避免写太多到 if err!=nilfunc CheckError(err error) {if err!=nil{fmt.Fprintf(os.Stderr,"Fatal error:%s",err.Error())os.Exit(1)}}//自定义logfunc Log(v... interface{}) {log.Println(v...)}func main() { server_listener,err:=net.Listen("tcp","localhost:8848")CheckError(err)defer server_listener.Close()Log("Waiting for clients connect")for{new_conn,err:=server_listener.Accept()CheckError(err)go ServerMsgHandler(new_conn)}}//服务端消息处理func ServerMsgHandler(conn net.Conn) {//存储被截断的数据tmpbuf:=make([] byte,0)buf:=make([] byte,1024)defer conn.Close()//接收解包readchan:=make(chan [] byte,16)go ReadChan(readchan)for{//读取客户端发来的消息n,err:=conn.Read(buf)if err!=nil{fmt.Println("connection close")return}//解包tmpbuf = protocol.Depack(append(tmpbuf,buf[:n]...))fmt.Println("client say:",string(tmpbuf))Msg:=tmpbuf//向客户端发送消息go WriteMsgToClient(conn)beatch :=make(chan byte)//心跳计时,默认30秒go HeartBeat(conn,beatch,30)//检测每次Client是否有数据传来go HeartChanHandler(Msg,beatch)}}//处理心跳,根据HeartChanHandler判断Client是否在设定时间内发来信息func HeartBeat(conn net.Conn,heartChan chan byte,timeout int) {select {case hc:=<-heartChan:Log("<-heartChan:",string(hc))conn.SetDeadline(time.Now().Add(time.Duration(timeout)*time.Second))breakcase <-time.After(time.Second*30):Log("timeout")conn.Close()}}//服务端向客户端发送消息func WriteMsgToClient(conn net.Conn) {talk:="wordpress"//将信息封包smsg:=protocol.Enpack([]byte(talk))conn.Write(smsg)}//处理心跳channelfunc HeartChanHandler( n [] byte,beatch chan byte) {for _,v:=range n{beatch<-v}close(beatch)}//从channell中读取数据func ReadChan(readchan chan [] byte) {for{select {case data:=<-readchan:Log(string(data))}}}
现在配上一张图,Server端不断给Client端发送消息"wordpress",Client不断向Server端汇报当前时间。
阅读全文
1 0
- 从零开始写Go网络通信框架(4)——全双工收发消息
- 从零开始写Go网络通信框架(2)——自定义通讯协议
- 从零开始写Go网络通信框架(3)——对长连接的处理
- 从零开始写Go网络通信框架(5)——断线重连
- 从零开始写Go网络通信框架(1)——基本的Socket Client/Server的编写
- (3)java网络socket通信---半双工、全双工
- scoket网络通信收发消息
- 网络基础知识(一)半双工与全双工
- 单工、半双工、全双工通信
- 网络的全双工与半双工
- WebSocket全双工通信入门教程
- 单工通信、半双工通信和全双工通信
- 同步,异步,全双工,半双工区别(总结)——扫盲篇
- socketpair创建双向通信的管道(全双工通信)
- 套接字(全双工)实现进程间通信
- 单工、半双工、全双工、异步通信、同步通信
- 全双工 半双工 单工 通信,同步和异步(待续)
- openstack从零开始(2)——基础知识openstack中消息通信
- CSS里面水平垂直居中的问题
- kali下tomcat安装出错
- Spring Data Redis提供的几种序列化的比较
- extern "C"
- Oracle视图
- 从零开始写Go网络通信框架(4)——全双工收发消息
- 在Firefox中关闭缓存
- 自定义放大镜插件 兼容ie6
- 【LeetCode515 Find Largest Value in Each Tree Row】二叉树每行的最大值
- 利用Flume将MySQL表数据准实时抽取到HDFS
- 编码是件有逻辑的事情
- sqlite 怎么开启wal机制
- java初学者的历程
- java并发测试用例模板