[Go]TCP服务中读写进行协程分离
读写两部分进行一下分离,中间通过chan进行传递数据 ,这样可以方便的在write中进行一些业务处理
single/snet/tcpconn.go
package snet import (
"bufio"
"fmt"
"log"
"net"
) type Conn struct {
IP string
Port uint32
TCPConn *net.TCPConn
MsgChan chan []byte
ExitChan chan bool
Closed bool
} func NewConn(IP string, Port uint32) *Conn {
s := &Conn{
IP: IP,
Port: Port,
MsgChan:make(chan []byte),
ExitChan: make(chan bool),
}
return s
} func (c *Conn) Start() {
log.Printf("%s:%d start...\n", c.IP, c.Port)
go func() {
addr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%d", c.IP, c.Port))
if err != nil {
log.Println("resolve tcp addr err ", err)
return
}
listener, err := net.ListenTCP("tcp4", addr)
if err != nil {
log.Println("listen tcp err ", err)
return
}
var connid uint32
connid =
for {
conn, err := listener.AcceptTCP()
if err != nil {
log.Println("accept tcp err ", err)
continue
}
c.TCPConn = conn
go c.StartRead()
go c.StartWrite()
connid++
}
}()
select {}
}
func (c *Conn) StartRead() {
log.Println("read groutine is waiting")
defer c.Stop()
defer log.Println("read groutine exit")
reader := bufio.NewReader(c.TCPConn)
for {
lineBytes, err := reader.ReadBytes('\n')
if err != nil {
log.Println("startread read bytes error ", err)
break
}
len:=len(lineBytes)
line:=lineBytes[:len-]
log.Println("start read from client ",string(line))
go c.HandleMsg(line)
}
}
func (c *Conn) StartWrite() {
log.Println("write groutine is waiting")
defer log.Println("write groutine exit")
for {
select {
case data := <-c.MsgChan:
if _, err := c.TCPConn.Write(data); err != nil {
log.Println("startwrite conn write error ", err)
return
}
log.Println("start write from server ",string(data))
case <-c.ExitChan:
return
}
}
}
func (c *Conn) HandleMsg(data []byte) {
res := fmt.Sprintf("res:%s", string(data)) c.MsgChan <- []byte(res)
}
func (c *Conn) Stop() {
if c.Closed {
return
}
c.Closed = true
c.ExitChan <- true c.TCPConn.Close()
close(c.ExitChan)
close(c.MsgChan)
}
测试代码,使用上面的包:
server.go
package main import "single/snet"
func main(){
s:=snet.NewConn("0.0.0.0",)
s.Start()
}

[Go]TCP服务中读写进行协程分离的更多相关文章
- 038_go语言中的状态协程
代码演示: package main import ( "fmt" "math/rand" "sync/atomic" "time ...
- yield学习续:yield return迭代块在Unity3D中的应用——协程
必读好文推荐: Unity协程(Coroutine)原理深入剖析 Unity协程(Coroutine)原理深入剖析再续 上面的文章说得太透彻,所以这里就记一下自己的学习笔记了. 首先要说明的是,协程并 ...
- Unity中巧用协程和游戏对象的生命周期处理游戏重启的问题
主要用到协程(Coroutines)和游戏对象的生命周期(GameObject Lifecycle)基础知识,巧妙解决了游戏重启的问题. 关于协程,这里有篇文章我觉得写的非常好,理解起来也很容易.推荐 ...
- python中线程 进程 协程
多线程:#线程的并发是利用cpu上下文的切换(是并发,不是并行)#多线程执行的顺序是无序的#多线程共享全局变量#线程是继承在进程里的,没有进程就没有线程#GIL全局解释器锁#只要在进行耗时的IO操作的 ...
- Android中的Coroutine协程原理详解
前言 协程是一个并发方案.也是一种思想. 传统意义上的协程是单线程的,面对io密集型任务他的内存消耗更少,进而效率高.但是面对计算密集型的任务不如多线程并行运算效率高. 不同的语言对于协程都有不同的实 ...
- python编程中的并发------协程gevent模块
任务例子:喝水.吃饭动作需要耗时1S 单任务:(耗时20s) for i in range(10): print('a正在喝水') time.sleep(1) print('a正在吃饭') time. ...
- [Go]TCP服务中增加消息队列与工作池
之前的处理中每一个连接都会创建一个主groutine , 每个连接中的主groutine中创建出读groutine 和写groutine 每个连接处理业务再单独开出一个groutine ,这样如果有1 ...
- Python中进程线程协程小结
进程与线程的概念 进程 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程.需要强调的是:同一个程序执行两次,那也是两个进程. 进程:资源管理单位(容器). 线程:最小执行单位,管理线程的是进程. ...
- main函数中如何等待协程运行完毕
使用channel同步 package main import ( "fmt" ) func printNumber(num int, c chan struct{}) { fmt ...
随机推荐
- Exponial
Description Everybody loves big numbers (if you do not, you might want to stop reading at this point ...
- 2018HDU多校训练一 A - Maximum Multiple
Given an integer nn, Chiaki would like to find three positive integers xx, yy and zzsuch that: n=x+y ...
- ARTS-S c语言统计程序运行时间
#include <stdio.h> #include <sys/time.h> #include <unistd.h> int main() { struct t ...
- 每周一练 之 数据结构与算法(Stack)
最近公司内部在开始做前端技术的技术分享,每周一个主题的 每周一练,以基础知识为主,感觉挺棒的,跟着团队的大佬们学习和复习一些知识,新人也可以多学习一些知识,也把团队内部学习氛围营造起来. 我接下来会开 ...
- .NET Core RSA 指南与增强扩展 RSAExtensions
一. 前言 RSA 作为最常用的非对称加密算法,在我们的实际使用中还是比较常见的,特别是对接支付十有八九都会遇到,或者是其他需要数据安全的业务场景.在 .NET Framework 以及 .NET C ...
- 关于 Kafka 的一些面试题目
上周客串了一下面试官,在这里就简单记录一下期间我问到的一些关于 Kafka 的面试题目,这些都是我平时在学习 Kafka 的一些总结要点. 谈谈你对 kafka 的整体认识? 问这个问题主要是想知道面 ...
- poj 2955 Brackets (区间dp基础题)
We give the following inductive definition of a “regular brackets” sequence: the empty sequence is a ...
- 《Java基础知识》Java 运算符
计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富的运算符来操纵变量.我们可以把运算符分成以下几组: 算术运算符 关系运算符 位运算符 逻辑运算符 赋值运算符 其他运 ...
- 《Dotnet9》系列-FluentValidation在C# WPF中的应用
时间如流水,只能流去不流回! 点赞再看,养成习惯,这是您给我创作的动力! 本文 Dotnet9 https://dotnet9.com 已收录,站长乐于分享dotnet相关技术,比如Winform.W ...
- mybatis源码学习(二)--mybatis+spring源码学习
这篇笔记主要来就,mybatis是如何利用spring的扩展点来实现和spring的整合 1.mybatis和spring整合之后,我们就不需要使用sqlSession.selectOne()这种方式 ...