本篇讲nsqlookupd中tcp.go、tcp_server.go

tcp_server.go位于util目录下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package util
       
import (
    "log"
    "net"
    "runtime"
    "strings"
)

type TCPHandler interface {
    Handle(net.Conn)
}

/**
*本方法开始接受客户端连接,并注册处理方法
*/
func TCPServer(listener net.Listener, handler TCPHandler) {
    log.Printf("TCP: listening on %s", listener.Addr().String())

    for {
        clientConn, err := listener.Accept()
        if err != nil {
            if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
                log.Printf("NOTICE: temporary Accept() failure - %s", err.Error())
                runtime.Gosched()
                continue
            }
            // theres no direct way to detect this error because it is not exposed
            if !strings.Contains(err.Error(), "use of closed network connection") {
                log.Printf("ERROR: listener.Accept() - %s", err.Error())
            }
            break
        }
        //handler由调用时通过参数传入,作为工具方法,将可能的变化放在外部,以保证本方法可以有尽可能多的适用范围
        go handler.Handle(clientConn)
    }

    log.Printf("TCP: closing %s", listener.Addr().String())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package nsqlookupd

import (
    "io"
    "log"
    "net"

    "github.com/bitly/nsq/util"
)

type tcpServer struct {
    context *Context
}

//
// nsqlookupd接收到tcp数据时,会调用本方法处理。
//实现了/util/tcp_server.go中定义的TCPHandler接口
//

func (p *tcpServer) Handle(clientConn net.Conn) {
    log.Printf("TCP: new client(%s)", clientConn.RemoteAddr())

    // The client should initialize itself by sending a 4 byte sequence indicating
    // the version of the protocol that it intends to communicate, this will allow us
    // to gracefully upgrade the protocol away from text/line oriented to whatever...
    //客户端在初始化自己的时候,需要发送4字节的数据用来标识它自己所有使用协议版本。将来升级协议的时候可以避免使用旧协议的客户端不能使用。
    buf := make([]byte, 4)
    _, err := io.ReadFull(clientConn, buf)
    if err != nil {
        log.Printf("ERROR: failed to read protocol version - %s", err.Error())
        return
    }
    //获取协议内容
    protocolMagic := string(buf)

    log.Printf("CLIENT(%s): desired protocol magic '%s'", clientConn.RemoteAddr(), protocolMagic)

    //util\Protocol.go中定义了一个Protocol的接口
    var prot util.Protocol

    switch protocolMagic {
    case "  V1":
        //当前只支持"  V1"协议(前两有两个空格,所以总共是4字节),协议在nsqlookupd\lookup_protocol_v1.go文件中定义,这里创建了LookupProtocolV1的实例
        //LookupProtocolV1实现了Protocol接口
        prot = &LookupProtocolV1{context: p.context}
    default:
        //如果不是"  V1"协议,则协议出错,断开链接,返回。
        util.SendResponse(clientConn, []byte("E_BAD_PROTOCOL"))
        clientConn.Close()
        log.Printf("ERROR: client(%s) bad protocol magic '%s'", clientConn.RemoteAddr(), protocolMagic)
        return
    }

    //如果是"  V1"f协议,这里就进入了LookupProtocolV1的IOLoop方法。此方法里有for死循环运行,直到出现error时,才会执行下面的代码。
    err = prot.IOLoop(clientConn)
    if err != nil {
        log.Printf("ERROR: client(%s) - %s", clientConn.RemoteAddr(), err.Error())
        return
    }
}

从以上代码可看出,tcp.go和tcp_server.go主要功能就是监听并接受TCP请求,收到请求后,将数据转给lookup_protocol_v1.go来处理。这个下篇再讲。

go语言nsq源码解读六 tcp.go、tcp_server.go的更多相关文章

  1. go语言nsq源码解读九 tcp和http中channel、topic的增删

    通过前面多篇文章,nsqlookupd基本已经解读完毕了,不过在关于channel和topic的增删上还比较模糊,所以本篇将站在宏观的角度来总结一下,tcp.go和http.go两个文件中关于chan ...

  2. go语言nsq源码解读八 http.go、http_server.go

    这篇讲另两个文件http.go.http_server.go,这两个文件和第六讲go语言nsq源码解读六 tcp.go.tcp_server.go里的两个文件是相对应的.那两个文件用于处理tcp请求, ...

  3. (转)go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin

    转自:http://www.baiyuxiong.com/?p=886 ---------------------------------------------------------------- ...

  4. go语言 nsq源码解读三 nsqlookupd源码nsqlookupd.go

    从本节开始,将逐步阅读nsq各模块的代码. 读一份代码,我的思路一般是: 1.了解用法,知道了怎么使用,对理解代码有宏观上有很大帮助. 2.了解各大模块的功能特点,同时再想想,如果让自己来实现这些模块 ...

  5. go语言nsq源码解读七 lookup_protocol_v1.go

    本篇将解读nsqlookup处理tcp请求的核心代码文件lookup_protocol_v1.go. 1234567891011121314151617181920212223242526272829 ...

  6. go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin

    nsqlookupd: 官方文档解释见:http://bitly.github.io/nsq/components/nsqlookupd.html 用官方话来讲是:nsqlookupd管理拓扑信息,客 ...

  7. go语言nsq源码解读一-基本介绍

    简单介绍一下nsq. 参考 http://feilong.me/2013/05/nsq-realtime-message-processing-system 的介绍:NSQ是由知名短链接服务商bitl ...

  8. go语言 nsq源码解读四 nsqlookupd源码options.go、context.go和wait_group_wrapper.go

    本节会解读nsqlookupd.go文件中涉及到的其中三个文件:options.go.context.go和wait_group_wrapper.go. options.go 123456789101 ...

  9. go语言nsq源码解读五 nsqlookupd源码registration_db.go

    本篇将讲解registration_db.go文件. 1234567891011121314151617181920212223242526272829303132333435363738394041 ...

随机推荐

  1. MySQL 菜鸟入门“秘籍”

    一.MySQL简介 1.什么是数据库 ? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不 ...

  2. 【基础】CSS实现多重边框的5种方式

    简言 目前最优雅地实现多重边框的方案是利用CSS3 的 box-shadow属性,但如果要兼容老的浏览器,则需要选择其它的方案.本文简要地列举了几种多重边框的实现方案,大家可以根据项目实际及兼容性要求 ...

  3. javascript学习笔记(四) Number 数字类型

    数字格式化方法toFixed().toExponential().toPrecision(),三个方法都四舍五入 toFixed() 方法指定小数位个数  toExponential() 方法 用科学 ...

  4. 在Redis Sentinel环境下,jedis该如何配置

    在Redis主从复制架构中,如果master出现了故障,则需要人工将slave提升为master,同时,通知应用侧更新master的地址.这样方式比较低效,对应用侧影响较大. 为了解决这个问题,Red ...

  5. Spring,@Controller,@RequestMapping, @ResponseBody,@RequestParam

    1.@Controller,放在类的上方,使类生效; 2.@RequestMapping,,指定一个映射,method为访问方式,headers为含有指定请求头 3. @ResponseBody将返回 ...

  6. Collections模块下的Counter

    class Counter(dict) 这个类是dict的子类,对哈希类型的项进行计数,元素被存储为字典的键,他们的计数将作为字典的键值. 主要介绍两个方法: 1.初始化方法:__init__(*ar ...

  7. 几大时尚前端UI框架的IE支持

    这个文章的Topic比较符合我们这些身在Stone Age用户环境中的开发者所考虑的因素 1.先说目前最火最酷的:Semantic-UI 目前版本:0.17.0 Browser Support Las ...

  8. AWS技术会议笔记

    Intel和云: SDI:软件定义架构 3D-XPointer:可以媲美内存速度的SSD 应用可以控制L3 Cache的使用 Helix物联网设备用 精益创业之路: 如何快速获得第一批用户---先要养 ...

  9. CSS的display:table

    好久都没有写博客了,似乎总是觉得少了些什么-- 刚好最近在工作中遇到了一个新的东西display:table,这个也是css的布局的一种,而且又是display的,之前已经写过了display的fle ...

  10. JAVA 语法2

    1.算术运算符 运算符 运算规则 范例 结果 + 正号 +3 3 + 加 2+3 5 + 连接字符串 "中"+"国" "中国" - 负号 i ...