当前位置:   article > 正文

Go语言学习笔记—golang TCP编程

golang tcp


一 基础知识

1.1 网络编程分类

网络编程有两种:

  1. TCP socket 编程,是网络编程的主流。之所以叫 Tcp socket 编程,是因为底层是基于 Tcp/ip 协议的. 比如: QQ 聊天
  2. b/s 结构的 http 编程,我们使用浏览器去访问服务器时,使用的就是 http 协议,而 http 底层依旧是用 tcp socket 实现的。比如: 京东商城

1.2 协议

TCP/IP(Transmission Control Protocol/Internet Protocol)的简写,中文译名为传输控制协议/因特网互联协议,又叫网络通讯协议,这个协议是 Internet 最基本的协议、Internet 国际互联网络的基础,简单地说,就是由网络层的 IP 协议和传输层的 TCP 协议组成的。

在这里插入图片描述

1.3 OSI 与 Tcp/ip 参考模型

在这里插入图片描述

QQ间相互通讯案例:

在这里插入图片描述

1.4 ip地址

每个 internet 上的主机和路由器都有一个 ip 地址,它包括网络号和主机号,ip 地址有 ipv4(32位)或者 ipv6(128 位). 可以通过 ipconfig 来查看

在这里插入图片描述

1.5 端口

我们这里所指的端口不是指物理意义上的端口,而是特指 TCP/IP 协议中的端口,是逻辑意义上的端口。

如果把 IP 地址比作一间房子,端口就是出入这间房子的门。真正的房子只有几个门,但是一个 IP 地址的端口 可以有 65536(即:256×256)个之多!端口是通过端口号来标记的,端口号只有整数,范围是从 0 到 65535(256×256-1)

在这里插入图片描述

端口分类:

  • 0 号是保留端口.
  • 1-1024 是固定端口(程序员不要使用)又叫有名端口,即被某些程序固定使用,一般程序员不使用.
    22: SSH 远程登录协议 23: telnet 使用 21: ftp 使用
    25: smtp 服务使用 80: iis 使用 7: echo 服务
  • 1025-65535 是动态端口。这些端口,程序员可以使用.

注意事项:

  1. 在计算机(尤其是做服务器)要尽可能的少开端口
  2. 一个端口只能被一个程序监听
  3. 如果使用 netstat –an 可以查看本机有哪些端口在监听
  4. 可以使用 netstat –anb 来查看监听端口的 pid,在结合任务管理器关闭不安全的端口

二 tcp socket 编程流程

2.1 服务端的处理流程

  1. 监听端口 8888
  2. 接收客户端的 tcp 链接,建立客户端和服务器端的链接.
  3. 创建 goroutine,处理该链接的请求(通常客户端会通过链接发送请求包)

2.2 客户端的处理流程

  1. 建立与服务端的链接
  2. 发送请求数据[终端],接收服务器端返回的结果数据
  3. 关闭链接

2.3 程序示意图

在这里插入图片描述

  1. 服务端监听端口8888,客户端链接8888端口后,建立链接
  2. 服务端主线程§ 接收到客户端链接时,开启一个协程
  3. 处理客户端的请求,使得我们可以做一些分支来处理请求

三 net包

使用go做socket网络开发使用的是 net 包

import "net"
  • 1

net包提供了可移植的网络I/O接口,包括TCP/IP、UDP、域名解析和Unix域socket。

虽然本包提供了对网络原语的访问,大部分使用者只需要Dial、Listen和Accept函数提供的基本接口;以及相关的Conn和Listener接口。crypto/tls包提供了相同的接口和类似的Dial和Listen函数。

官方示例

Dial函数和服务端建立连接:

conn, err := net.Dial("tcp", "google.com:80")
if err != nil {
   
	// handle error
}
fmt.Fprintf(conn, "GET / HTTP/1.0\r\n\r\n")
status, err := bufio.NewReader(conn).ReadString('\n')
// ...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Listen函数创建的服务端:

ln, err := net.Listen("tcp", ":8080")
if err != nil {
   
	// handle error
}
for {
   
	conn, err := ln.Accept()
	if err != nil {
   
		// handle error
		continue
	}
	go handleConnection(conn)
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

四 net包重要类型

4.1 type Dialer

type Dialer struct {
   
    // Timeout是dial操作等待连接建立的最大时长,默认值代表没有超时。
    // 如果Deadline字段也被设置了,dial操作也可能更早失败。
    // 不管有没有设置超时,操作系统都可能强制执行它的超时设置。
    // 例如,TCP(系统)超时一般在3分钟左右。
    Timeout time.Duration
    // Deadline是一个具体的时间点期限,超过该期限后,dial操作就会失败。
    // 如果Timeout字段也被设置了,dial操作也可能更早失败。
    // 零值表示没有期限,即遵守操作系统的超时设置。
    Deadline time.Time
    // LocalAddr是dial一个地址时使用的本地地址。
    // 该地址必须是与dial的网络相容的类型。
    // 如果为nil,将会自动选择一个本地地址。
    LocalAddr Addr
    // DualStack允许单次dial操作在网络类型为"tcp",
    // 且目的地是一个主机名的DNS记录具有多个地址时,
    // 尝试建立多个IPv4和IPv6连接,并返回第一个建立的连接。
    DualStack bool
    // KeepAlive指定一个活动的网络连接的生命周期;如果为0,会禁止keep-alive。
    // 不支持keep-alive的网络连接会忽略本字段。
    KeepAlive time.Duration
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Dialer类型包含与某个地址建立连接时的参数。

每一个字段的零值都等价于没有该字段。因此调用Dialer零值的Dial方法等价于调用Dial函数。

*func (Dialer) Dial

func (d *Dialer) Dial(network, address string) (Conn, error)
  • 1

Dial在指定的网络上连接指定的地址。参见Dial函数获取网络和地址参数的描述。

4.2 type Listener

type Listener interface {
   
    // Addr返回该接口的网络地址
    Addr() Addr
    // Accept等待并返回下一个连接到该接口的连接
    Accept() (c Conn, err error)
    // Close关闭该接口,并使任何阻塞的Accept操作都会不再阻塞并返回错误。
    Close() error
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Listener是一个用于面向流的网络协议的公用的网络监听器接口。多个线程可能会同时调用一个Listener的方法。

func Listen

func Listen(net, laddr string) (Listener, error)
  • 1

返回在一个本地网络地址laddr上监听的Listener。网络类型参数net必须是面向流的网络:

“tcp”、“tcp4”、“tcp6”、“unix"或"unixpacket”。参见Dial函数获取laddr的语法。

4.3 type Conn

type Conn interface {
   
    // Read从连接中读取数据
    // Read方法可能会在超过某个固定时间限制后超时返回错误,该错误的Timeout()方法返回真
    Read(b []byte) (n int, err error)
    // Write从连接中写入数据
    // Write方法可能会在超过某个固定时间限制后超时返回错误,该错误的Timeout()方法返回真
    Write(b []byte) (n int, err error)
    // Close方法关闭该连接
    // 并会导致任何阻塞中的Read或Write方法不再阻塞并返回错误
    Close() error
    // 返回本地网络地址
    LocalAddr() Addr
    // 返回远端网络地址
    RemoteAddr() Addr
    // 设定该连接的读写deadline,等价于同时调用SetReadDeadline和SetWriteDeadline
    // deadline是一个绝对时间,超过该时间后I/O操作就会直接因超时失败返回而不会阻塞
    // deadline对之后的所有I/O操作都起效,而不仅仅是下一次的读或写操作
    // 参数t为零值表示不设置期限
    SetDeadline(t time
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/753935
推荐阅读
相关标签
  

闽ICP备14008679号