tcp 服务端
2017-09-06 17:48
23 查看
1.新建TcpServer
2.接受tcp请求接口
3.业务处理
4.user client struct
5.数据packet 解包
type TcpServer struct { // 记录每个IP的连接数量 perIPConnCounter ipmanager.PerIPConnCounter ln net.Listener }
func(tc *TcpServer) Start() { var lastPerIPErrorTime time.Time //开始接收tcp连接请求 ln, err := net.Listen("tcp", ":9998") if err != nil { log.Println("Listen", err.Error()) return} tc.ln = ln // 接收并处理连接请求 for { c, err := tc.acceptConn(ln, &lastPerIPErrorTime) if err != nil { panic("Room" + err.Error()) break } // 启动worker去处理连接 go tc.serve(c) } }
2.接受tcp请求接口
func(tc *TcpServer) acceptConn(ln net.Listener, lastPerIPErrorTime *time.Time) (net.Conn, error) { for { c, err := ln.Accept() if err != nil { if c != nil { log.Println("[FATAL] net.Listener returned non-nil conn and non-nil error : ", err.Error()) } if netErr, ok := err.(net.Error); ok && netErr.Temporary() { log.Println("[ERROR] Temporary error when accepting new connections: ", err.Error()) time.Sleep(time.Second) continue } if err != io.EOF && !strings.Contains(err.Error(), "use of closed network connection") { log.Println("[ERROR] Permanent error when accepting new connections: ", err.Error()) return nil, err } return nil, io.EOF } if c == nil { panic("BUG: net.Listener returned (nil, nil)") } //ConnectionTimeout 超时时间 c.SetReadDeadline(time.Now().Add(time.Duration(ConnectionTimeout) * time.Second)) //MaxConnSperIp 最大连接数 if MaxConnSperIp > 0 { pic := tc.wrapPerIPConn(c) if pic == nil { if time.Since(*lastPerIPErrorTime) > time.Minute { log.Println("[ERROR] The number of connections from ") *lastPerIPErrorTime = time.Now() } continue } c = pic } return c, nil } }
func(tc *TcpServer) wrapPerIPConn(c net.Conn) net.Conn { ip := ipmanager.GetUint32IP(c) if ip == 0 { return c } n := tc.perIPConnCounter.Register(ip) //MaxConnSperIp 最大连接数 if n > MaxConnSperIp { tc.perIPConnCounter.Unregister(ip) c.Close() return nil } return ipmanager.AcquirePerIPConn(c, ip, &tc.perIPConnCounter) }
3.业务处理
func(tc *TcpServer) serve(conn net.Conn) { defer func() { conn.Close() if err := recover(); err != nil { log.Println("readPacket", err) return } }() uc := NewUserClient(conn) go readPacket(uc, uc.ChildStopChan) for { select { case message, ok := <-uc.PacketDataChan: if !ok { log.Println("packet is get error") continue } switch message.GetPacketType() { case packet.APPLICATION_SEND: //业务处理 log.Println("业务处理", message) default: log.Println("invalid messageReceived msg:", message) break } case <-uc.LogOutStopChan: goto LogOut } } LogOut: defer func() { close(uc.ChildStopChan) close(uc.LogOutStopChan) close(uc.PacketDataChan) }() log.Println("LogOut close conn") }
4.user client struct
type UserClient struct { Conn net.Conn ChildStopChan chan bool LogOutStopChan chan bool PacketDataChan chan packet.Packet } func NewUserClient(conn net.Conn) *UserClient { return &UserClient{Conn: conn, ChildStopChan: make(chan bool, 1), LogOutStopChan: make(chan bool, 1), PacketDataChan: make(chan packet.Packet, 100), } }
5.数据packet 解包
funcreadPacket(uc *UserClient, rStop <-chan bool) { defer func() { if err := recover(); err != nil { log.Println("readPacket", err) return } }() for { select { case <-rStop: log.Println("readPacket", "readPacket get stop cmd") goto Stop default: pt, err := proto.ReadPacket(uc.Conn) if err != nil { log.Println("ReadPacket", err) uc.LogOutStopChan <- true goto Stop } //ConnectionTimeout 超时时间 uc.Conn.SetReadDeadline(time.Now().Add(time.Duration(ConnectionTimeout) * time.Second)) if pt != nil { uc.PacketDataChan <- pt } } } Stop: log.Println("conn stop ...") }
相关文章推荐
- 第5章-unix网络编程 TCP/服务端程序示例
- TCP-客户端连接服务端
- Socket(Tcp)通信服务端
- [转载]C# TCP实现多个客户端与服务端 数据 与 文件的传输
- TCP客户端频繁连接退出,服务端避免内存的重复开辟
- TCP服务端和客户端的框架
- java 使用TCP实现单聊的功能。(客户端和服务端聊天)
- TCP 上传图片到服务端
- 基于 IOCP 的通用异步 Windows Socket TCP 高性能服务端组件的设计与实现
- 从keep-alive原理 分析TCP游戏服务端心跳包的实用功能
- tcp并发服务端
- 基于TCP实现简单的客户端服务端的消息传递
- 基于TCP的服务端/客户端
- Linux网络编程之socket简单通信TCP--服务端代码
- Boost.Asio C++ 网络编程之五:TCP回显客户端/服务端
- Tcp服务端判断客户端是否断开连接
- TCP模拟客户端和服务端小例
- 使用erlang ranch tcp开发服务端
- [Java]命令行模拟TCP客户端与服务端的简单小程序遇到的问题(基础不牢!扎实和亲手实践比什么都重要!)
- Windows网络编程学习笔记(3) 编写一个TCP服务端