读写两部分进行一下分离,中间通过chan进行传递数据 ,这样可以方便的在write中进行一些业务处理

single/snet/tcpconn.go

  1. package snet
  2.  
  3. import (
  4. "bufio"
  5. "fmt"
  6. "log"
  7. "net"
  8. )
  9.  
  10. type Conn struct {
  11. IP string
  12. Port uint32
  13. TCPConn *net.TCPConn
  14. MsgChan chan []byte
  15. ExitChan chan bool
  16. Closed bool
  17. }
  18.  
  19. func NewConn(IP string, Port uint32) *Conn {
  20. s := &Conn{
  21. IP: IP,
  22. Port: Port,
  23. MsgChan:make(chan []byte),
  24. ExitChan: make(chan bool),
  25. }
  26. return s
  27. }
  28.  
  29. func (c *Conn) Start() {
  30. log.Printf("%s:%d start...\n", c.IP, c.Port)
  31. go func() {
  32. addr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", c.IP, c.Port))
  33. if err != nil {
  34. log.Println("resolve tcp addr err ", err)
  35. return
  36. }
  37. listener, err := net.ListenTCP("tcp4", addr)
  38. if err != nil {
  39. log.Println("listen tcp err ", err)
  40. return
  41. }
  42. var connid uint32
  43. connid =
  44. for {
  45. conn, err := listener.AcceptTCP()
  46. if err != nil {
  47. log.Println("accept tcp err ", err)
  48. continue
  49. }
  50. c.TCPConn = conn
  51. go c.StartRead()
  52. go c.StartWrite()
  53. connid++
  54. }
  55. }()
  56. select {}
  57. }
  58. func (c *Conn) StartRead() {
  59. log.Println("read groutine is waiting")
  60. defer c.Stop()
  61. defer log.Println("read groutine exit")
  62. reader := bufio.NewReader(c.TCPConn)
  63. for {
  64. lineBytes, err := reader.ReadBytes('\n')
  65. if err != nil {
  66. log.Println("startread read bytes error ", err)
  67. break
  68. }
  69. len:=len(lineBytes)
  70. line:=lineBytes[:len-]
  71. log.Println("start read from client ",string(line))
  72. go c.HandleMsg(line)
  73. }
  74. }
  75. func (c *Conn) StartWrite() {
  76. log.Println("write groutine is waiting")
  77. defer log.Println("write groutine exit")
  78. for {
  79. select {
  80. case data := <-c.MsgChan:
  81. if _, err := c.TCPConn.Write(data); err != nil {
  82. log.Println("startwrite conn write error ", err)
  83. return
  84. }
  85. log.Println("start write from server ",string(data))
  86. case <-c.ExitChan:
  87. return
  88. }
  89. }
  90. }
  91. func (c *Conn) HandleMsg(data []byte) {
  92. res := fmt.Sprintf("res:%s", string(data))
  93.  
  94. c.MsgChan <- []byte(res)
  95. }
  96. func (c *Conn) Stop() {
  97. if c.Closed {
  98. return
  99. }
  100. c.Closed = true
  101. c.ExitChan <- true
  102.  
  103. c.TCPConn.Close()
  104. close(c.ExitChan)
  105. close(c.MsgChan)
  106. }

测试代码,使用上面的包:

server.go

  1. package main
  2.  
  3. import "single/snet"
  4. func main(){
  5. s:=snet.NewConn("0.0.0.0",)
  6. s.Start()
  7. }

[Go]TCP服务中读写进行协程分离的更多相关文章

  1. 038_go语言中的状态协程

    代码演示: package main import ( "fmt" "math/rand" "sync/atomic" "time ...

  2. yield学习续:yield return迭代块在Unity3D中的应用——协程

    必读好文推荐: Unity协程(Coroutine)原理深入剖析 Unity协程(Coroutine)原理深入剖析再续 上面的文章说得太透彻,所以这里就记一下自己的学习笔记了. 首先要说明的是,协程并 ...

  3. Unity中巧用协程和游戏对象的生命周期处理游戏重启的问题

    主要用到协程(Coroutines)和游戏对象的生命周期(GameObject Lifecycle)基础知识,巧妙解决了游戏重启的问题. 关于协程,这里有篇文章我觉得写的非常好,理解起来也很容易.推荐 ...

  4. python中线程 进程 协程

    多线程:#线程的并发是利用cpu上下文的切换(是并发,不是并行)#多线程执行的顺序是无序的#多线程共享全局变量#线程是继承在进程里的,没有进程就没有线程#GIL全局解释器锁#只要在进行耗时的IO操作的 ...

  5. Android中的Coroutine协程原理详解

    前言 协程是一个并发方案.也是一种思想. 传统意义上的协程是单线程的,面对io密集型任务他的内存消耗更少,进而效率高.但是面对计算密集型的任务不如多线程并行运算效率高. 不同的语言对于协程都有不同的实 ...

  6. python编程中的并发------协程gevent模块

    任务例子:喝水.吃饭动作需要耗时1S 单任务:(耗时20s) for i in range(10): print('a正在喝水') time.sleep(1) print('a正在吃饭') time. ...

  7. [Go]TCP服务中增加消息队列与工作池

    之前的处理中每一个连接都会创建一个主groutine , 每个连接中的主groutine中创建出读groutine 和写groutine 每个连接处理业务再单独开出一个groutine ,这样如果有1 ...

  8. Python中进程线程协程小结

    进程与线程的概念 进程 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程.需要强调的是:同一个程序执行两次,那也是两个进程. 进程:资源管理单位(容器). 线程:最小执行单位,管理线程的是进程. ...

  9. main函数中如何等待协程运行完毕

    使用channel同步 package main import ( "fmt" ) func printNumber(num int, c chan struct{}) { fmt ...

随机推荐

  1. CodeForces - 1221E Game With String(不平等博弈)

    Alice and Bob play a game. Initially they have a string s1,s2,…,sns1,s2,…,sn, consisting of only cha ...

  2. POJ3261 Milks patterns(后缀数组)

    Farmer John has noticed that the quality of milk given by his cows varies from day to day. On furthe ...

  3. (全国多校重现赛一) H Numbers

    zk has n numbers a1,a2,...,ana1,a2,...,an. For each (i,j) satisfying 1≤i<j≤n, zk generates a new ...

  4. ARTS-S mongo关闭与启动

    关闭 mongo admin --eval "db.shutdownServer()" 删除dbdata目录下的mongo.lock 启动 /usr/bin/mongod --db ...

  5. stm32 io操作 头文件规范

    在stm32众多项目开发中,有太多的对io进行操作,若置1或清0,使用官方库提供的函数,固然方便,规范,但是需要包含标准的库,尺寸较大,还得处理不同版本兼容问题,包括io初始化也太繁琐,于是操作原子等 ...

  6. Python流程控制之分支结构

    目录 if/else结构 多重if结构 嵌套if结构 练习 if/else结构 if如果,else否则 # java if(){ }else{ } # python if 条件: 语句 else: 语 ...

  7. 大数据学习笔记——Hadoop高可用完全分布式模式完整部署教程(包含zookeeper)

    高可用模式下的Hadoop集群搭建 本篇博客将会在之前写过的Linux的完整部署的基础上进行,暂时不会涉及到伪分布式或者完全分布式模式搭建,由于HA模式涉及到的配置文件较多,维护起来也较为复杂,相信学 ...

  8. 10分钟理解BFC原理

    10 分钟理解 BFC 原理 一.常见定位方案 在讲 BFC 之前,我们先来了解一下常见的定位方案,定位方案是控制元素的布局,有三种常见方案: 普通流 (normal flow) 在普通流中,元素按照 ...

  9. 封装读取文件(node js)

    我们都会简单的读取文件,今天我们就来讲一下用函数封装读取文件. 1.首先我们要先建好文件 2.我们在index.js里面写入代码: var http=require('http'); var fs=r ...

  10. poj 1270 Following Orders (拓扑排序+回溯)

    Following Orders Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5473   Accepted: 2239 ...