news 2026/5/5 6:43:35

Go Socket编程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Go Socket编程

Socket是计算机网络中用于在节点内发送或接收数据的内部端点.具体来说.是网络软件(协议栈)中端点的一种表示.包含通信协议 目标地址 状态等.是系统资源的一种形式.它在网络中所处的位置大致就是如图所示的Socket API层.位于应用层与传输层之间.其中的传输层就是TCP/IP所在的地方.开发人员平时通过代码编写的应用程序大多属于应用层范畴.

如图所示.SocketAPI起到的就是连接应用层与传输层的作用.

Socket API的诞生就是为了应用程序能更方便的将数据经由传输层来传输.所以它本质上是对TCP/IP的运用进行了一层封装.然后应用程序直接调用SocketAPI接口进行通信.

总结来说.Socket是进程间数据传输的媒介.为了保证连接的可靠性.需要特别注意建立连接和关闭连接的过程.为了确保准确 完整的传输数据.客户端和服务端会来回进行了多次网络通信才完成连接的创建和关闭.这也是在运用一个连接时所花费的额外成本.

TCP Socket:

Go语言中进行网络编程.相比传统的网络编程更加简洁.Go语言提供了net包来处理Socket.net包对Socket连接过程进行了抽象和封装.无论使用什么协议建立了什么形式的连接.都只需要net.Dial()函数即可.

定义如下.

func Dial(net,addr string) (Conn,error)

net参数是网络协议的名字.addr参数是IP地址或域名.而端口号以":"的形式跟随在地址或域名的后面.端口号可选.如果连接成功.则返回连接对象.否则返回error.

除Dial()函数外.还有一个名为DialTCP()的函数用来建立TCP连接.

定义如下.

func DialTCP(network string,laddr,raddr *TCPAddr) (*TCPConn,error)

network参数可以是tcp或者tcp4或者tcp6.laddr为本地地址.通常为nil.raddr为目的地址.为TCPAddr类型的指针.该函数返回一个*TCPConn对象.可通过Read()和Write()方法传递数据.

Dial()函数的几种常见协议调用方式如下:

TCP连接:

TCP连接直接通过net.Dial("tcp","ip:port")的形式调用.代码如下.

conn,err := net.Dial("tcp","192.168.0.1:8087")

UDP连接:

UDP连接直接通过net.Dial("udp","ip:port")的形式调用.代码如下.

net.Dial("udp","192.168.0.2:8088")

目前.Dial()函数支持如下几种网络协议.tcp tcp4(仅限IPv4) tcp6(仅限IPv6) udp udp4(仅限IPv4) udp6(仅限IPv6) ip ip4(仅限IPv4)和ip6(仅限IPv6).

在成功建立连接后.就可以进行数据的发送和接收.使用Write()方法发送数据.使用Read方法接收数据.

UDP Socket:

由于UDP是无连接的.所以服务器端只需要指定IP地址和端口号.然后监听该地址.等待客户端与之建立连接.即可通信.

在Go语言中创建UDP Socket.可以通过如下函数或方法来实现.

1).创建监听地址

创建监听地址使用ResolveUDPAddr()函数.定义如下.

func ResolveUDPAddr(network,address string) (*UDPAddr,error)

2).创建监听连接

创建监听连接使用ListenUDP()函数.定义如下.

func ListenUDP(network string,laddr UDPAddr) (UDPConn,error)

3).接收UDP数据

接收UDP数据使用ReadFromUDP()方法.定义如下.

func(c *UDPConn) ReadFromUDP(b []byte) (int,*UDPAddr,error)

4).写入数据到UDP

func(c *UDPConn) WriteToUDP (b []byte,addr *UDPAddr) (int,error)

Socket简易聊天:

服务端每收到一个连接.就让一个goroutine去通过Socket和客户端进行交流.goroutine执行流程.先接收信息.在发送信息.客户端从终端获取输入.发送给指定的IP地址和端口服务器.接收服务信息.

TCP Socket服务端:

package main import ( "bufio" "fmt" "net" "os" ) func main() { listenSock, err := net.Listen("tcp", "127.0.0.1:8080") if err != nil { Log("监听失败", err) } for { connectSock, err := listenSock.Accept() defer connectSock.Close() if err != nil { Log("接收请求失败", err) } } } func Work(sock net.Conn) { for { var buf [1024]byte n, err := sock.Read(buf[:]) if err != nil { Log("读取数据出错", err) } fmt.Printf("%v 说: %v", sock.RemoteAddr().String(), string(buf[:n])) var str string reader := bufio.NewReader(os.Stdin) str, err = reader.ReadString('\n') if err != nil { Log("发送失败", err) } sock.Write([]byte(str)) } } func Log(msg string, err error) { fmt.Println(msg, err) os.Exit(-1) }

TCP Socket客户端:

package main import ( "bufio" "fmt" "net" "os" ) func main() { server, err := net.Dial("tcp", "127.0.0.1:8080") if err != nil { fmt.Println("拨号失败:", err) os.Exit(-1) } defer server.Close() for { var str string var buf [1024]byte reader := bufio.NewReader(os.Stdin) str, err := reader.ReadString('\n') if err != nil { fmt.Println("发送失败:", err) os.Exit(-1) } server.Write([]byte(str)) var n int n, err = server.Read(buf[:]) if err != nil { fmt.Println("读取失败:", err) os.Exit(-1) } fmt.Printf("%v 说: %v", server.RemoteAddr().String(), string(buf[:n])) } }

UDP Socket服务端:

UDP服务器无连接.接收到消息.将消息输出.在回复收到字样后.服务器处于死循环中.只要客户端拨号的IP和端口是UDP服务器的IP和端口.该UDP服务器都可以接收.也不需要额外的goroutine来处理多个客户端的信息.

func main() { conn, err := net.ListenUDP("udp", &net.UDPAddr{ IP: net.ParseIP("127.0.0.1"), Port: 8888, }) if err != nil { fmt.Println("ListenUDP error:", err) os.Exit(-1) } defer conn.Close() for { var buf [1024]byte n, addr, err := conn.ReadFromUDP(buf[:]) if err != nil { fmt.Println("接收消息出错:", err) } fmt.Println(addr.String(), string(buf[:n])) conn.WriteToUDP([]byte("收到"), addr) } }

UDP Socket客户端:

package main import ( "bufio" "fmt" "net" "os" "strings" ) func main() { con, err := net.DialUDP("udp", nil, &net.UDPAddr{ IP: net.ParseIP("127.0.0.1"), Port: 8888, }) if err != nil { fmt.Println("拨号失败", err) } for { reader := bufio.NewReader(os.Stdin) str, _ := reader.ReadString('\n') str = strings.Trim(str, "\r\n") if strings.ToUpper(str) == "STOP" { fmt.Println("退出") return } con.Write([]byte(str)) var buf [1024]byte n, _, _ := con.ReadFromUDP(buf[:]) fmt.Println(con.RemoteAddr().String(), string(buf[:n])) } }

语雀地址https://www.yuque.com/itbosunmianyi/xg8vfe?

《Go.》 密码:xbkk 欢迎大家访问.提意见.

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 6:42:39

终极指南:5分钟搞定网易云音乐NCM文件解密与转换

终极指南:5分钟搞定网易云音乐NCM文件解密与转换 【免费下载链接】ncmdump 转换网易云音乐 ncm 到 mp3 / flac. Convert Netease Cloud Music ncm files to mp3/flac files. 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdump 你是否曾经在网易云音乐下载…

作者头像 李华
网站建设 2026/5/5 6:33:27

单目视频3D追踪技术:从原理到工程实践

1. 项目概述:单目视频3D追踪的突破性方案 TrackingWorld 是一种基于单目摄像头的密集3D环境追踪技术,它能够在普通2D视频流中重建出厘米级精度的三维空间运动轨迹。不同于传统的特征点匹配方案,这套系统直接对视频中的每个像素进行三维位置估…

作者头像 李华
网站建设 2026/5/5 6:23:56

告别NTP!用PTP(ptp4l+phc2sys)在Linux上实现亚微秒级时间同步

告别NTP!用PTP在Linux上实现亚微秒级时间同步的完整指南 在金融高频交易系统中,两个服务器之间哪怕只有500微秒的时间差,就可能导致套利机会的错失;在5G基站同步场景中,时间偏差超过110纳秒就会引发信号干扰&#xff1…

作者头像 李华
网站建设 2026/5/5 6:23:47

2026年揭秘!口碑超棒的立达、特吕茨施勒、赐来福电气专修生产厂家

在纺纱纺织行业,立达、特吕茨施勒、赐来福等品牌的设备以其高性能和稳定性备受青睐。然而,这些进口设备一旦出现故障,维修难题却让众多企业头疼不已。今天,就为大家揭秘一家在2026年口碑超棒的进口纺织机械电气专修生产厂家——郑…

作者头像 李华
网站建设 2026/5/5 6:23:15

NI-DAQmx定时同步应用

​LabVIEW 环境下NI-DAQmx 定时与同步的实现方法、适用场景、技术特点、使用注意事项,并与传统方案对比,给出可直接落地的工程案例,帮助工程师快速构建高精度、多通道、多设备协同的数据采集系统。全文约 1900 字,内容严谨、可直接…

作者头像 李华