本篇讲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. OVS 中的哈希表: shash

    shash出现在OVS的代码中,定义如下:   struct hmap_node {     size_t hash;     struct hmap_node * next; };   struct ...

  2. 百度站长平台MIP

    使用说明 MIP(Mobile Instant Pages - 移动网页加速器),是一套应用于移动网页的开放性技术标准.通过提供 MIP-HTML 规范.MIP-JS 运行环境以及 MIP-Cache ...

  3. 多线程编程 NSOperation

     前言 1.NSThread的使用,虽然也可以实现多线程编程,但是需要我们去管理线程的生命周期,还要考虑线程同步.加锁问题,造成一些性能上的开销.我们也可以配合使用NSOperation和NSOper ...

  4. N-Queens(N皇后问题)

    题目: The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no two que ...

  5. Aop实现SqlSugar自动事务

    http://www.cnblogs.com/jaycewu/p/7733114.html

  6. Python Django开发中XSS内容过滤问题的解决

    from:http://stackoverflow.com/questions/699468/python-html-sanitizer-scrubber-filter 通过下面这个代码就可以把内容过 ...

  7. 托管C++线程锁实现

    最近由于工作需要,开始写托管C++,由于C++11中的mutex,和future等类,托管C++不让调用(报错),所以自己实现了托管C++的线程锁. 该类可确保当一个线程位于代码的临界区时,另一个线程 ...

  8. numpy用法归纳

    1.生成数组 import numpy as np 把python列表转换为数组 >>> np.array([1, 2, 3]) array([1, 2, 3]) 把python的r ...

  9. HTTP协议、Ajax请求

    今天这篇文章呢,主要讲的就是关于HTTP协议.Ajax请求以及一些相关的小知识点.虽然内容不算多,可是是很重点的东西~ HTTP协议 1. http:超文本传输协议.简单.快速.灵活.无状态.无连接. ...

  10. python_code list_3

    >>> seq=['foo','x41','?','***']>>> def func(x): return x.isalnum() >>> li ...