Go语言实现简单的TCP、UDP链接

⼀、使用Golang创建⼀一个TCP连接
 
1.服务端处理理流程
  a.监听端口

    b.接受客户端的链接

  c.创建Goroutine,处理这个链接(⼀个服务端要链接多个客户端,所以使用Goroutine⾮常简单)

  题外话:要是用Java、C#服务这边每⼀个请求都开⼀个线程处理的话,顶多⼏千个,但是Goroutine就⾮常简单。

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
package main
 
import (
    "fmt"
    "net"
)
 
func main() {
    //1.建立监听端口
    listen, err := net.Listen("tcp", "0.0.0.0:20000")
    if err != nil {
        fmt.Println("listen failed, err:", err)
        return
    }
 
    fmt.Println("listen Start...:")
 
    for {
        //2.接收客户端的链接
        conn, err := listen.Accept()
        if err != nil {
            fmt.Printf("accept failed, err:%v\n", err)
            continue
        }
        //3.开启一个Goroutine,处理链接
        go process(conn)
    }
}
 
//处理请求,类型就是net.Conn
func process(conn net.Conn) {
 
    //处理结束后关闭链接
    defer conn.Close()
    for {
        var buf [128]byte
        n, err := conn.Read(buf[:])
        if err != nil {
            fmt.Printf("read from conn failed, err:%v", err)
            break
        }
        fmt.Printf("recv from client, content:%v\n", string(buf[:n]))
    }
 
}

2.客户端处理流程

  a.和服务端建立一个链接
  b.进行数据的收发
  c.关闭链接 
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
package main
 
import (
    "bufio"
    "fmt"
    "net"
    "os"
    "strings"
)
 
func main() {
    //1.建立一个链接(Dial拨号)
    conn, err := net.Dial("tcp", "0.0.0.0:20000")
    if err != nil {
        fmt.Printf("dial failed, err:%v\n", err)
        return
    }
 
    fmt.Println("Conn Established...:")
 
    //读入输入的信息
    reader := bufio.NewReader(os.Stdin)
    for {
        data, err := reader.ReadString('\n')
        if err != nil {
            fmt.Printf("read from console failed, err:%v\n", err)
            break
        }
 
        data = strings.TrimSpace(data)
        //传输数据到服务端
        _, err = conn.Write([]byte(data))
        if err != nil {
            fmt.Printf("write failed, err:%v\n", err)
            break
        }
    }
}
执⾏⼀下:
客户端:
服务端: 

⼆、使用Golang创建⼀个HTTP连接
A.HTTP协议是基于TCP协议之上的⽂本协议。
B.每行⽂本使⽤\r\n结尾,当连续两个\r\n时,表示整个数据包结束。
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
package main
 
import (
    "fmt"
    "io"
    "net"
)
 
func main() {
    conn, err := net.Dial("tcp", "www.baidu.com:80")
    if err != nil {
        fmt.Printf("dial failed, err:%v\n", err)
        return
    }
 
    data := "GET / HTTP/1.1\r\n"
    data += "HOST: www.baidu.com\r\n"
    data += "connection: close\r\n"
    data += "\r\n\r\n"
 
    //写入数据
    _, err = io.WriteString(conn, data)
    if err != nil {
        fmt.Printf("wirte string failed, err:%v\n", err)
        return
    }
 
    var buf [1024]byte
    for {
        //读取返回的数据
        n, err := conn.Read(buf[:])
        if err != nil || n == 0 {
            break
        }
 
        fmt.Println(string(buf[:n]))
    }
}
 
三、使⽤用Golang创建⼀个UDP连接
1.服务流程,相比于TCP连接需要Accept一个链接,UDP不需要进⾏这步操作,服务端代码如下:
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
package main
 
import (
    "fmt"
    "net"
)
 
func main() {
    //建立一个UDP的监听,这里使用的是ListenUDP,并且地址是一个结构体
    listen, err := net.ListenUDP("udp", &net.UDPAddr{
        IP:   net.IPv4(0, 0, 0, 0),
        Port: 8080,
    })
    if err != nil {
        fmt.Printf("listen failed, err:%v\n", err)
        return
    }
 
    for {
        var data [1024]byte
        //读取UDP数据
        count, addr, err := listen.ReadFromUDP(data[:])
        if err != nil {
            fmt.Printf("read udp failed, err:%v\n", err)
            continue
        }
 
        fmt.Printf("data:%s addr:%v count:%d\n", string(data[0:count]), addr, count)
        //返回数据
        _, err = listen.WriteToUDP([]byte("hello client"), addr)
        if err != nil {
            fmt.Printf("write udp failed, err:%v\n", err)
            continue
        }
    }
}

2.客户端流程

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
package main
 
import (
    "fmt"
    "net"
)
 
func main() {
    // 创建连接
    socket, err := net.DialUDP("udp4", nil, &net.UDPAddr{
        IP:   net.IPv4(127, 0, 0, 1),
        Port: 8080,
    })
    if err != nil {
        fmt.Println("连接失败!", err)
        return
    }
    defer socket.Close()
    // 发送数据
    senddata := []byte("hello server!")
    _, err = socket.Write(senddata)
    if err != nil {
        fmt.Println("发送数据失败!", err)
        return
    }
    // 接收数据
    data := make([]byte, 4096)
    read, remoteAddr, err := socket.ReadFromUDP(data)
    if err != nil {
        fmt.Println("读取数据失败!", err)
        return
    }
    fmt.Println(read, remoteAddr)
    fmt.Printf("%s\n", data)
}

posted @   奋斗的大橙子  阅读(6371)  评论(1编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
点击右上角即可分享
微信分享提示