Go实现简单的Socket服务端笔记(七)

Session增加唯一ID,拆分socket中的Read方法

增加ID为了以后判断闲置超时; 拆分Read方法方便扩展协议

本文代码查看github:
https://github.com/zboyco/go-server/tree/step-7

  1. 修改AppSession结构体,增加ID和activeDateTime属性,为超时管理做准备
//客户端结构体
type AppSession struct {
	ID             int64     //连接唯一标识
	conn           net.Conn  //socket连接
	activeDateTime time.Time //最后活跃时间
}
  1. 将socket.go 中接收数据的方法,移植到client.go中,作为AppSession的方法使用
//读取数据
func (session *AppSession) Read() ([]byte, error) {

	//定义一个数据接收Buffer
	var buf [10240]byte

	//读取数据,io.Reader 需要传入一个byte切片
	n, err := session.conn.Read(buf[0:])

	if err != nil {
		return nil, err
	}

	//更新最后活跃时间
	session.activeDateTime = time.Now()
	return buf[0:n], nil
}

client.go完整代码如下:

package server

import (
	"net"
	"time"
)

//客户端结构体
type AppSession struct {
	ID             int64     //连接唯一标识
	conn           net.Conn  //socket连接
	activeDateTime time.Time //最后活跃时间
}

//发送数据
func (session *AppSession) Send(buf []byte) {
	session.conn.Write(buf)
	//更新最后活跃时间
	session.activeDateTime = time.Now()
}

//读取数据
func (session *AppSession) Read() ([]byte, error) {

	//定义一个数据接收Buffer
	var buf [10240]byte

	//读取数据,io.Reader 需要传入一个byte切片
	n, err := session.conn.Read(buf[0:])

	if err != nil {
		return nil, err
	}

	//更新最后活跃时间
	session.activeDateTime = time.Now()
	return buf[0:n], nil
}

修改socket.go中handleClient函数,执行AppSession的Read来获取数据
socket.go 完整代码如下:

package server

import (
	"fmt"
	"net"
	"time"
)

//服务结构
type Server struct {
	ip            string
	port          int
	clientCounter int64
	OnError       func(error)
	OnMessage     func(*AppSession, []byte)
}

//新建一个服务
func New(ip string, port int) *Server {
	return &Server{
		ip:            ip,
		port:          port,
		clientCounter: 0,
	}
}

//开始监听
func (server *Server) Start() {
	//定义一个本机端口
	localAddress, _ := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", server.ip, server.port))

	//监听端口
	tcpListener, err := net.ListenTCP("tcp", localAddress)

	if err != nil {
		fmt.Println("监听出错, ", err)
		if server.OnError != nil {
			server.OnError(err)
		}
		return
	}

	//程序返回后关闭socket
	defer tcpListener.Close()

	for {
		fmt.Println("等待客户连接...")

		//开始接收连接
		conn, err := tcpListener.Accept()

		if err != nil {
			fmt.Println("客户连接失败, ", err)
			if server.OnError != nil {
				server.OnError(err)
			}
			continue
		}

		//客户端ID数+1
		server.clientCounter++

		appSession := &AppSession{
			ID:             server.clientCounter,
			conn:           conn,
			activeDateTime: time.Now(),
		}

		//启用goroutine处理
		go handleClient(server, appSession)
	}
}

//读取数据
func handleClient(server *Server, session *AppSession) {
	//获取连接地址
	remoteAddr := session.conn.RemoteAddr()

	fmt.Println("客户[", session.ID, "]地址:", remoteAddr)

	for {
		fmt.Println("等待接收客户[", session.ID, "]的数据...", session.activeDateTime)

		bytes, err := session.Read()

		if err != nil {
			fmt.Println("客户[", session.ID, "]数据接收错误, ", err)
			if server.OnError != nil {
				server.OnError(err)
			}
			return
		}

		if server.OnMessage == nil {
			fmt.Println("错误,未找到数据处理方法!")
			continue
		}
		server.OnMessage(session, bytes)
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值