TCP UDP done
parent
05e21d15c5
commit
a5b20d8c4b
|
@ -17,3 +17,20 @@ IPv4这个版本规定,网络地址由32个二进制位组成,我们通常
|
||||||
也就是说,我们还需要一个参数,表示这个数据包到底供哪个程序(进程)使用。这个参数就叫做"端口”(port),它其实是每一个使用网卡的程序的编号。
|
也就是说,我们还需要一个参数,表示这个数据包到底供哪个程序(进程)使用。这个参数就叫做"端口”(port),它其实是每一个使用网卡的程序的编号。
|
||||||
每个数据包都发到主机的特定端口,所以不同的程序就能取到自己所需要的数据。
|
每个数据包都发到主机的特定端口,所以不同的程序就能取到自己所需要的数据。
|
||||||
“端口"是0到65535之间的一个整数,正好16个二进制位。0到1023的端口被系统占用,用户只能选用大于1023的端口。有了IP和端口我们就能实现唯一确定互联网上一个程序,进而实现网络间的程序通信。
|
“端口"是0到65535之间的一个整数,正好16个二进制位。0到1023的端口被系统占用,用户只能选用大于1023的端口。有了IP和端口我们就能实现唯一确定互联网上一个程序,进而实现网络间的程序通信。
|
||||||
|
|
||||||
|
|
||||||
|
TCP服务端程序的处理流程:
|
||||||
|
|
||||||
|
1.监听端口
|
||||||
|
2.接收客户端请求建立链接
|
||||||
|
3.创建goroutine处理链接。
|
||||||
|
|
||||||
|
一个TCP客户端进行TCP通信的流程如下:
|
||||||
|
|
||||||
|
1.建立与服务端的链接
|
||||||
|
2.进行数据收发
|
||||||
|
3.关闭链接
|
||||||
|
|
||||||
|
TCP粘包
|
||||||
|
引申知识点:
|
||||||
|
大端和小端{https://zhuanlan.zhihu.com/p/680366680}
|
|
@ -12,10 +12,11 @@ import (
|
||||||
//TCP server端
|
//TCP server端
|
||||||
|
|
||||||
func process(conn net.Conn) {
|
func process(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
var tmp = make([]byte, 1024)
|
var tmp = make([]byte, 1024)
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
for {
|
for {
|
||||||
n, err := conn.Read(tmp[:])
|
n, err := conn.Read(tmp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("read failed on:", err)
|
log.Fatal("read failed on:", err)
|
||||||
return
|
return
|
|
@ -0,0 +1,28 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"course/networkProgram/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
// socket_stick/client/main.go
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
conn, err := net.Dial("tcp", "127.0.0.1:30000")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("dial failed, err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
msg := `Hello, Hello. How are you?`
|
||||||
|
b, err := proto.Encode(msg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("encode failed, err", err)
|
||||||
|
}
|
||||||
|
conn.Write(b)
|
||||||
|
//time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
proto "course/networkProgram/protocol"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// socket_stick/server/main.go
|
||||||
|
func proc(conn net.Conn) {
|
||||||
|
defer conn.Close()
|
||||||
|
reader := bufio.NewReader(conn)
|
||||||
|
for {
|
||||||
|
msg, err := proto.Decode(reader)
|
||||||
|
if err == io.EOF {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("decode msg failed, err:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("收到client发来的数据:", msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
listen, err := net.Listen("tcp", "127.0.0.1:30000")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("listen failed, err:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer listen.Close()
|
||||||
|
for {
|
||||||
|
conn, err := listen.Accept()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("accept failed, err:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go proc(conn)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
//UDP client
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
socket, err := net.DialUDP("udp", nil, &net.UDPAddr{
|
||||||
|
IP: net.IPv4(127, 0, 0, 1),
|
||||||
|
Port: 40000,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("连接服务端失败,err", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer socket.Close()
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
reply := make([]byte, 512)
|
||||||
|
for {
|
||||||
|
fmt.Print("> ")
|
||||||
|
msg, _ := reader.ReadString('\n')
|
||||||
|
socket.Write([]byte(msg))
|
||||||
|
//收回复的数据
|
||||||
|
n, _, err := socket.ReadFromUDP(reply)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("read reply msg failed:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Print(string(reply[:n]))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UDP sever
|
||||||
|
func main() {
|
||||||
|
conn, err := net.ListenUDP("udp", &net.UDPAddr{
|
||||||
|
IP: net.IPv4(127, 0, 0, 1),
|
||||||
|
Port: 40000,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("listen udp failed:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
//不需要建立链接,直接收发数据
|
||||||
|
data := make([]byte, 1024)
|
||||||
|
for {
|
||||||
|
n, addr, err := conn.ReadFromUDP(data)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("read from udp failed:", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("%s\n", data[:n])
|
||||||
|
reply := string(data[:n])
|
||||||
|
reply = strings.ToUpper(reply)
|
||||||
|
//发送数据
|
||||||
|
conn.WriteToUDP([]byte(reply), addr)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
// socket_stick/proto/proto.go
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Encode 将消息编码
|
||||||
|
func Encode(message string) ([]byte, error) {
|
||||||
|
// 读取消息的长度,转换成int32类型(占4个字节)
|
||||||
|
var length = int32(len(message))
|
||||||
|
var pkg = new(bytes.Buffer)
|
||||||
|
// 写入消息头
|
||||||
|
err := binary.Write(pkg, binary.LittleEndian, length)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 写入消息实体
|
||||||
|
err = binary.Write(pkg, binary.LittleEndian, []byte(message))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return pkg.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode 解码消息
|
||||||
|
func Decode(reader *bufio.Reader) (string, error) {
|
||||||
|
// 读取消息的长度
|
||||||
|
lengthByte, _ := reader.Peek(4) // 读取前4个字节的数据
|
||||||
|
lengthBuff := bytes.NewBuffer(lengthByte)
|
||||||
|
var length int32
|
||||||
|
err := binary.Read(lengthBuff, binary.LittleEndian, &length)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
// Buffered返回缓冲中现有的可读取的字节数。
|
||||||
|
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
|
||||||
|
}
|
Loading…
Reference in New Issue