1.TCP服务端编程模型
1.图示
![]()
2.服务端处理流程
- 1.监听端口
- 2.接收客户端的连接
- 3.创建
goroutine,处理该连接
package main
import (
"fmt"
"net"
)
func handle(conn net.Conn) {
defer conn.Close()
for {
var buf[128]byte
length, err := conn.Read(buf[:])
if err != nil {
fmt.Println("read from conn failed, err: ", err)
break
}
str := string(buf[:length])
fmt.Println("receive from client, message: ", str)
}
}
func main() {
fmt.Println("listen on 50000...")
listen, err := net.Listen("tcp", "0.0.0.0:50000")
if err != nil {
fmt.Println("listen failed, err: \n", err)
return
}
for {
conn, err := listen.Accept()
if err != nil {
fmt.Println("accept failed, err: ", err)
continue
}
go handle(conn)
}
}
3.客户端编程模式
- 1.建立与服务端的连接
- 2.进行数据收发
- 3.关闭链接
package main
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
func main() {
conn, err := net.Dial("tcp", "localhost:50000")
if err != nil {
fmt.Println("Error dialing", err.Error())
return
}
defer conn.Close()
// 从终端获取用户输入
inputReader := bufio.NewReader(os.Stdin)
for {
// 以换行符作为结束
input, _ := inputReader.ReadString('\n')
// 去除终端输入字符串前后的换行
trimmedInput := strings.Trim(input, "\r\n")
// 当用户输入Q,就退出
if trimmedInput == "Q" {
return
}
_, err = conn.Write([]byte(trimmedInput))
if err != nil {
fmt.Println("write failed, err: ", err)
break
}
}
}
4.HTTP请求
- 1.HTTP协议是基于TCP协议上的文本协议
- 2.每行文本使用
\r\n结尾,当连续两个\r\n时,表示整个数据包结束
package main
import (
"fmt"
"io"
"net"
)
func main() {
conn, err := net.Dial("tcp", "www.baidu.com:80")
if err != nil {
fmt.Println("Error dialing", err.Error())
return
}
defer conn.Close()
data := "GET / HTTP/1.1\r\n"
data += "HOST: www.baidu.com\r\n"
data += "connection: close\r\n"
_, errors := io.WriteString(conn, data)
if errors != nil {
fmt.Println("write string failed, err: ", err)
}
var buf[1024]byte
for {
length, err := conn.Read(buf[:])
if err != nil || length == 0 {
break
}
fmt.Println(string(buf[:length]))
}
}
2.UDP协议
1.说明
- 1.用户数据报协议
- 2.无连接,直接进行数据发送
- 3.不可靠,没有时序
- 4.实时性比较好,通常用于视频直播相关领域
2.UDP服务端
package main
import (
"fmt"
"net"
)
func main() {
listen, err := net.ListenUDP("udp", &net.UDPAddr{
IP: net.IPv4(0,0,0,0),
Port: 8999,
Zone: "",
})
if err != nil {
fmt.Println("listen failed, err: ", err)
return
}
for {
var data [1024]byte
count, addr, err := listen.ReadFromUDP(data[:])
if err != nil {
fmt.Println("read udp failed, err: ", err)
continue
}
fmt.Printf("data: %s addr: %v count %d\n", data[0:count], addr, count)
_, errs := listen.WriteToUDP([]byte("hello client!"), addr)
if errs != nil {
fmt.Println("write udp failed, err: ", errs)
continue
}
}
}
3.UDP客户端
package main
import (
"fmt"
"net"
)
func main() {
client, err := net.DialUDP("udp", nil, &net.UDPAddr{
IP: net.IPv4(127, 0, 0, 1),
Port: 8999,
Zone: "",
})
if err != nil {
fmt.Println("连接失败:", err)
return
}
defer client.Close()
// 发送数据
sendData := []byte("hello server!")
_, errs := client.Write(sendData)
if errs != nil {
fmt.Println("发送数据失败:", errs)
return
}
// 接收数据
data := make([]byte, 4096)
read, remoteAddr, errors := client.ReadFromUDP(data)
if errors != nil {
fmt.Println("读取数据失败:", errors)
return
}
fmt.Println(read, remoteAddr)
fmt.Println(string(data))
}