这是我参与8月更文挑战的第20天,活动详情查看:8月更文挑战
TCP
传输控制协议, 属于ISO七层网络模型中的传输层. 它是面向连接, 提供可靠的传输服务
TCP特点
- 面向连接
- 保证可靠交付
- 只支持一对一通信
- 提供全双工通信
- 传输字节流数据
TCP的三次握手
- 客户端首先发送一个请给服务器, 表示想要建立连接的请求
- 服务器端收到建立连接请求后, 回传给客户端确认信息
- 客户端再回传给服务器确认收到服务器发送的确认信息
TCP的四次挥手
- 客户端发送一个释放连接的请求给服务器
- 服务器收到释放连接的请求后, 回传给客户端表示确认收到
- 服务器发送一个释放连接的请求给客户端
- 客户端收到释放连接的请求后, 回传给服务器表示确认收到
TCP服务端流程
-
通过net.Listen()进行网络监听, 获得一个Listener实例
type Listener interface { // 处理连接请求 Accept() (Conn, error) // 关闭当前监听 Close() error // 返回当前网络地址: ip + 端口号 Addr() Addr } -
通过listener.Accept()处理来自client的连接请求
-
通过一个goroutine来处理该连接请求
-
所有连接处理完毕之后, 关闭监听listener.Close()
TCP服务端代码
import (
"bufio"
"fmt"
"net"
)
func main() {
// 监听端口
listener, err := net.Listen("tcp", "127.0.0.1:1000")
if err != nil {
fmt.Println("listen failed: ", err)
return
}
fmt.Println("tcp: 127.0.0.1:1000 监听成功")
// 当程序退出的时候, 关闭监听
defer func() {
fmt.Println("listener closed")
listener.Close()
}()
for {
// 接收来自client的连接请求
c, err := listener.Accept()
// 请求错误
if err != nil {
fmt.Println("accept failed: ", err)
continue
}
// 处理连接
go dealConn(c)
}
}
func dealConn(c net.Conn) {
// 当连接处理完之后, 关闭连接
defer func() {
fmt.Println("conn closed")
c.Close()
}()
// 用于读取内容
reader := bufio.NewReader(c)
for {
data := make([]byte, 16)
n, err := reader.Read(data[:])
if err != nil {
fmt.Println("read failed: ", err)
break
}
fmt.Println("read success: ", string(data[:n]))
// 向client端返回数据
c.Write(data[:n])
}
}
TCP客户端流程
-
调用net.Dial函数建立连接, 返回一个Conn实例
type Conn interface { // 从连接中读取数据 Read(b []byte) (n int, err error) // 向连接中写入数据 Write(b []byte) (n int, err error) // 关闭当前连接 Close() error // 本机地址 LocalAddr() Addr // 远程主机地址 RemoteAddr() Addr // 超时时间 SetDeadline(t time.Time) error SetReadDeadline(t time.Time) error SetWriteDeadline(t time.Time) error }
- 调用Write函数向该连接写入数据
- 调用Read函数接收来自server端的响应
- 调用Close函数关闭该连接
TCP客户端代码
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
func main() {
// 建立连接 ip地址为: 127.0.0.1, 端口号为: 1000
c, err := net.Dial("tcp", "127.0.0.1:1000")
// 建立连接失败
if err != nil {
fmt.Println("dial failed: ", err)
return
}
// 在程序执行完之后, 关闭连接
defer func() {
fmt.Println("client conn closed!")
c.Close()
}()
}
func requestTCP(c net.TCPConn) {
// 如果建立连接成功, 则向server端发送数据
// 准备好要发送的数据 Write方法接收一个byte类型的切片
reader := bufio.NewReader(os.Stdin)
for {
inData, _ := reader.ReadString('\n')
data := strings.Trim(inData, "\n")
// 如果输入的为Q, 则退出程序
if strings.ToUpper(data) == "Q" {
break
}
// 向server端发送数据
_, err := c.Write([]byte(data))
// 数据发送失败, 输出错误信息
if err != nil {
fmt.Println("write failed: ", err)
}
// 数据发送成功
fmt.Println("write success")
// 从server端接收数据
serverData := make([]byte, 16)
n, err := c.Read(serverData)
if err != nil {
fmt.Println("client recv failed: ", err)
break
}
fmt.Println("client recv success: ", string(data[:n]))
}
}