Golang网络编程(一)
本文最后更新于:2024年7月6日 早上
1. 前言
最近工作当中用Python写了非常多的socket代码,用于和底层的设备之间进行交互。然而我的方式比较原始,自己在一个基础的socket上不断地进行扩展。总所周知,Python的网络编程界有一个大名鼎鼎的Twisted框架,Twisted是已经一个维护了十余年的成熟项目,基于事件驱动设计的高性能网络编程框架。奈何这个框架的学习成本比较高,再由于笔者最近在学习Go语言,所以想着不如在Go语言中折腾一下网络编程,以下就是笔者学习阶段的一些总结。
2. Socket编程起源
socket起源于Unix,而Unix/Linux 基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式 来操作。Socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭)
在 Unix/Linux 中的 Socket 编程主要通过调用 listen
, accept
, write
read
等函数来实现的. 具体如下图所示:
3. 再回首——Python中的socket
在进入到Go语言的世界前,和我再来回顾一下,Python中Socket编程的基础实例:
Server.py
1 |
|
Client.py
1 |
|
显而易见,Python的代码哲学还是有优点的。好了,整理好心情,和Python道声再见,我们进入Go的世界。
4. Go SOCKET基础概念
4.1 IP类型
net包中定义的IP类型直接就是byte数组:
1 |
|
我们可以使用func parseIP(s string) IP
来把一个IP地址转换成IP类型:
1 |
|
4.2 函数
4.2.1 funcResolveTCPAddr(net, addr string) (*TCPAddr, error)
ResolveTCPAddr函数的功能是解析TCP连接的地址,包含
ip和
port
net
:tcp
tcp4
tcp6
三选一,分别表示TCPv4,TCPv6和任意,默认是tcp4
addr
:主机的地址,可以是[ip+port]
,也可以是[domain+port]
,可以省略主机部分,表示本机地址
返回一个*TCPAddr
类型 ,表示一个TCP连接地址:
1 |
|
4.2.2 func ResolveIPAddr(net, addr string) (*IPAddr, error)
ResolveIPAddr
函数的功能是解析ip地址:
net
:ip
ip4
ip6
分别代表IPv4,IPv6以及任意。默认留空表示ip4
addr
:IP地址
返回一个*IPAddr
结构:
1 |
|
4.2.3 func Dial(network, address string) (Conn, error)
Dial
函数的功能是建立一个连接:
network
: 如果是TCP连接,对应tcp
tcp4
tcp6;如果是IP连接,对应ip ip4 ip6
。对于ip连接,需要在后面加一个冒号然后注明协议号或者协议名字address
:连接的地址,ip+port
或domain+port
形式,也可以省略主机地址表示本地地址217.0.0.1
返回一个net.Conn
接口对象,包含了连接的信息,我们可以使用该对象的Write()
和Read()
对连接进行读写。
1 |
|
与这个函数相对应的两个函数:
func DialTCP(net string, laddr, raddr *TCPAddr) (*TCPConn, error)
func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error)
分别表示建立TCP请求和IP请求,中间多的laddr
表示本地的地址,一般为nil
。
4.2.4 func (c *conn) Write(b []byte) (int, error)
向conn
连接对象中写入数据,即发送数据给对方,写入的数据是[]byte
类型,成功将返回发送的数据包字节数。
1 |
|
4.2.5 func (c *conn) Read(b []byte) (int, error)
从conn连接对象中读取数据,成功将返回读取到的字节数。
1 |
|
4.2.6 func Listen(net, laddr string) (Listener, error)
Listen函数在服务端使用,让服务端开始监听。
net
:和上面一样,可以是tcp
ip
相关的值laddr
:要监听的地址,ip+port
省略主机地址将使用本机地址127.0.0.1
相应的两个函数:
func ListenTCP(net string, laddr *TCPAddr) (*TCPListener, error)
:监听TCP连接func DialIP(netProto string, laddr, raddr *IPAddr) (*IPConn, error)
:监听IP连接
4.2.7 func (l *TCPListener) Accept() (Conn, error)
服务端开始监听需要使用Accept
函数来接受客户端连接,此时服务端将进入阻塞状态。
相应的还有一个
func (l *TCPListener) AcceptTCP() (*TCPConn, error)
5. Go 基础scoket代码实例
经过上面的介绍,相信大家对Go的socket编程已经有了一些了解。现在我们就来写一个server和client,实现功能:client发送数据到server,server将数据转成大写后返回。
server.go
1 |
|
client.go
1 |
|
6. 小结
至此,相信大家对Go的网络编程已经有了一个大致的了解。
后续的计划是
- Go并发socket编程
- Go的socket编程粘包处理
- 挑选一个成熟的Go网络编程框架进行学习
参考资料
马谦的博客:https://www.dyxmq.cn/code/golang/golang-socket-2.html
始于珞尘:https://juejin.im/entry/5aa8ebe46fb9a028de4467bd
《Go语言程序设计》