


An article to help you understand the basics of Go language network programming
What we have learnedTCP
and UDP
are collectively referred to as Socker
programming, also called Socket Programming.
Multiple machinesTo realize mutual communication, is actually a very complicated process. The bottom layer lays the network cable from , network cable interface,switch,router, at ProvisionsVarious protocols.
Go to the application layerQQ
,WeChat
, etc. software.
If there is no set of standards, and each programmer has to implement it by himself every time he uses it, it may not be as simple as losing his hair!
After havingSocker
, Socker
will hide various tedious underlying operations before the application layer. We may only need Socker.TCP
realizes the communication of TCP
protocol.
Go languageTCP
TCP is a stable and reliable long connection,
Since communication is involved, there must be two terminals, at least one is the server, and the other is Client, just like our Taobao, every time we open Taobao, we have to link to it. Of course, Taobao is not directly TCP
.
Server
Implement the server in Go, and concurrency on the server is very simple. You only need to allow one protocol for each connection. Just process it!
Code
package main import ( "bufio" "fmt" "net" ) func process(conn net.Conn) { defer conn.Close() for { reader := bufio.NewReader(conn) buf := make([]byte, 128) n, err := reader.Read(buf) if err != nil { fmt.Println("数据读取失败", err) return } recvStr := string(buf[:n]) fmt.Println("客户端发送过来的值:", recvStr) } } func main() { lister, err := net.Listen("tcp", "0.0.0.0:8008") if err != nil { fmt.Println("连接失败", err) } for { fmt.Println("等待建立连接,此时会阻塞住") conn, err := lister.Accept() //等待建立连接 fmt.Println("连接建立成功,继续") if err != nil { fmt.Println("建立连接失败", err) //继续监听下次链接 continue } go process(conn) } }
Client
Customer The end is very simple. Relatively speaking, there is no need for concurrency, only connection is required.
代码
package main import ( "bufio" "fmt" "net" "os" ) //客户端 func main() { conn, err := net.Dial("tcp", "192.168.10.148:8008") if err != nil { fmt.Println("连接服务器失败",err) } defer conn.Close() inputReader:=bufio.NewReader(os.Stdin) for{ fmt.Println(":") input,_:=inputReader.ReadString('\n') _, err = conn.Write([]byte(input)) if err != nil { fmt.Println("发送成功") } } }
执行结果
就这样,我们实现了服务端并发的处理所有客户端的请求。
粘包
我们先看一下什么是粘包。
服务端
package main import ( "bufio" "fmt" "io" "net" ) func process(conn net.Conn) { defer conn.Close() reader := bufio.NewReader(conn) buf := make([]byte, 1024) for { n, err := reader.Read(buf) //读完了 if err == io.EOF { fmt.Println("读完了") break } //读错了 if err != nil { fmt.Println("数据读取失败", err) return } recvStr := string(buf[:n]) fmt.Println("客户端发送过来的值:", recvStr) } } func main() { lister, err := net.Listen("tcp", "0.0.0.0:8008") if err != nil { fmt.Println("连接失败", err) return } defer lister.Close() for { fmt.Println("等待建立连接,此时会阻塞住") conn, err := lister.Accept() //等待建立连接 fmt.Println("连接建立成功,继续") if err != nil { fmt.Println("建立连接失败", err) //继续监听下次链接 continue } go process(conn) } }
客户端
package main import ( "fmt" "net" ) //客户端 func main() { conn, err := net.Dial("tcp", "192.168.10.148:8008") if err != nil { fmt.Println("连接服务器失败", err) } defer conn.Close() for i := 0; i < 10; i++ { sendStr := "hello world ads asdf asd fads fadsf ads ads asd asd ads " conn.Write([]byte(sendStr)) time.Sleep(time.Second) } }
注意:18行代码睡眠了1s
执行结果
If I comment the 18th line of code
##Execution result
It’s all in one line, what? What's happening? Shouldn't it be the same as before? ? ?
Every time a value is sent, it is received over there. How come this is all in one piece! ! !
The reason
The main reason is because we are the application layerSoftware is software running on the operating system. When we send a data to the server, it is Call the related interface of the operating system to send it. The operating system then goes through various complex operations and sends it to the other machine.
But the operating system has a buffer for sending data. By default, if the buffer has a size and the buffer is not full, the data will not be sent, so the above client is When sending data, the system's buffer was not full, and it was kept in the operating system's buffer. Finally, it was found that there was no data, so it was sent to the server all at once
But why does sleep(1)
work again? This is because the buffer is used by more than one program, and 1s is enough Other programs fill up the buffer and then send their own data. This is why the first operation is fine, but the second operation is problematic, because the second time is all filled up by our client
Solution to sticky packages
Tool function
We will solve Encapsulate the function of the encapsulation package
socker_sitck/stick.go
package socker_stick import ( "bufio" "bytes" "encoding/binary" "fmt" ) //Encode 将消息编码 func Encode(message string) ([]byte, error) { length := int32(len(message)) var pkg = new(bytes.Buffer) //写入消息头 err := binary.Write(pkg, binary.LittleEndian, length) if err != nil { fmt.Println("写入消息头失败", err) return nil, err } //写入消息实体 err = binary.Write(pkg, binary.LittleEndian, []byte(message)) if err != nil { fmt.Println("写入消息实体失败", err) return nil, err } return pkg.Bytes(), nil } //Decode解码消息 func Decode(reader *bufio.Reader) (string, error) { //读取信息长度 lengthByte, _ := reader.Peek(4) lengthBuff := bytes.NewBuffer(lengthByte) var length int32 err := binary.Read(lengthBuff, binary.LittleEndian, &length) if err != nil { return "", err } //BuffRead 返回缓冲区现有的可读的字节数 if int32(reader.Buffered()) < length+4 { return "", err } pack := make([]byte, int(4+length)) _, err = reader.Read(pack) if err != nil { return "", err } return string(pack[4:]), nil }
服务端
package main import ( "a3_course/socker_stick" "bufio" "fmt" "io" "net" ) func process(conn net.Conn) { defer conn.Close() reader := bufio.NewReader(conn) for { msg, err := socker_stick.Decode(reader) //读完了 if err == io.EOF { fmt.Println("读完了") break } //读错了 if err != nil { fmt.Println("数据读取失败", err) return } fmt.Println("客户端发送过来的值:", msg) } } func main() { lister, err := net.Listen("tcp", "0.0.0.0:8008") if err != nil { fmt.Println("连接失败", err) return } defer lister.Close() for { fmt.Println("等待建立连接,此时会阻塞住") conn, err := lister.Accept() //等待建立连接 fmt.Println("连接建立成功,继续") if err != nil { fmt.Println("建立连接失败", err) //继续监听下次链接 continue } go process(conn) } }
客户端
package main import ( "a3_course/socker_stick" "fmt" "net" ) //客户端 func main() { conn, err := net.Dial("tcp", "192.168.10.148:8008") if err != nil { fmt.Println("连接服务器失败", err) } defer conn.Close() for i := 0; i < 10; i++ { sendStr := "hello world ads asdf asd fads fadsf ads ads asd asd ads " data, err := socker_stick.Encode(sendStr) if err != nil { fmt.Println("编码失败",err) return } conn.Write(data) //time.Sleep(time.Second) } }
执行结果
这次真的不管执行几次,都是这样的结果
对了,只有TCP
才有粘包
Go语言UDP
UDP
是一个无连接协议,客户端不会在乎服务端有没有问题,客户端只管发,通常用于实时性比较高的领域
例如直播行业
服务端
package main import ( "fmt" "net" ) func main() { listen, err := net.ListenUDP("udp", &net.UDPAddr{ IP: net.IPv4(0, 0, 0, 0), Port: 8009, }) if err != nil { panic(fmt.Sprintf("udp启动失败,err:%v", err)) } defer listen.Close() for{ var data = make([]byte,1024) n, addr, err := listen.ReadFromUDP(data) if err != nil { panic(fmt.Sprintf("读取数据失败,err:%v", err)) } fmt.Println(string(data[:n]),addr,n) } }
客户端
package main import ( "fmt" "net" ) func main() { socker, err := net.DialUDP("udp", nil, &net.UDPAddr{ IP: net.IPv4(0, 0, 0, 0), Port: 8009, }) if err != nil { panic(fmt.Sprintf("连接服务器失败,err:%v", err)) } defer socker.Close() sendStr:="你好呀" _, err = socker.Write([]byte(sendStr)) if err != nil { panic(fmt.Sprintf("数据发送失败,err:%v", err)) } }
执行结果
总结
本次章节我们讲述了什么是TCP,什么是UDP。
并且编写了代码如何实现TCP服务端,TCP客户端,UDP服务端,UDP客户端。
讲述了为什么会出现粘包,该怎么解决粘包。
The above is the detailed content of An article to help you understand the basics of Go language network programming. For more information, please follow other related articles on the PHP Chinese website!

Golangisidealforbuildingscalablesystemsduetoitsefficiencyandconcurrency,whilePythonexcelsinquickscriptinganddataanalysisduetoitssimplicityandvastecosystem.Golang'sdesignencouragesclean,readablecodeanditsgoroutinesenableefficientconcurrentoperations,t

Golang is better than C in concurrency, while C is better than Golang in raw speed. 1) Golang achieves efficient concurrency through goroutine and channel, which is suitable for handling a large number of concurrent tasks. 2)C Through compiler optimization and standard library, it provides high performance close to hardware, suitable for applications that require extreme optimization.

Reasons for choosing Golang include: 1) high concurrency performance, 2) static type system, 3) garbage collection mechanism, 4) rich standard libraries and ecosystems, which make it an ideal choice for developing efficient and reliable software.

Golang is suitable for rapid development and concurrent scenarios, and C is suitable for scenarios where extreme performance and low-level control are required. 1) Golang improves performance through garbage collection and concurrency mechanisms, and is suitable for high-concurrency Web service development. 2) C achieves the ultimate performance through manual memory management and compiler optimization, and is suitable for embedded system development.

Golang performs better in compilation time and concurrent processing, while C has more advantages in running speed and memory management. 1.Golang has fast compilation speed and is suitable for rapid development. 2.C runs fast and is suitable for performance-critical applications. 3. Golang is simple and efficient in concurrent processing, suitable for concurrent programming. 4.C Manual memory management provides higher performance, but increases development complexity.

Golang's application in web services and system programming is mainly reflected in its simplicity, efficiency and concurrency. 1) In web services, Golang supports the creation of high-performance web applications and APIs through powerful HTTP libraries and concurrent processing capabilities. 2) In system programming, Golang uses features close to hardware and compatibility with C language to be suitable for operating system development and embedded systems.

Golang and C have their own advantages and disadvantages in performance comparison: 1. Golang is suitable for high concurrency and rapid development, but garbage collection may affect performance; 2.C provides higher performance and hardware control, but has high development complexity. When making a choice, you need to consider project requirements and team skills in a comprehensive way.

Golang is suitable for high-performance and concurrent programming scenarios, while Python is suitable for rapid development and data processing. 1.Golang emphasizes simplicity and efficiency, and is suitable for back-end services and microservices. 2. Python is known for its concise syntax and rich libraries, suitable for data science and machine learning.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

SublimeText3 English version
Recommended: Win version, supports code prompts!

SublimeText3 Chinese version
Chinese version, very easy to use

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software