这是我参与「第三届青训营 -后端场」笔记创作活动的第四篇笔记
服务端
- 创建监听socket
listener := net.Listen("tcp", "IP+port") - 启动监听
conn := listener.Accept() - 读取监听的数据
conn.Read() - 回写给客户端数据
conn.Write() - defer 注册关闭两个socket :listener,conn
func main() {
listener, err := **net.Listen**("tcp", "127.0.0.1:8989")
if err != nil {
fmt.Println("net.Listen err:", err)
return
}
defer listener.Close()
fmt.Println("服务器已启动,正在监听....")
conn, err := **listener.Accept()**
if err != nil {
fmt.Println("listener.accept err:", err)
return
}
defer conn.Close()
buf := make([]byte, 4096)
n, err := **conn.Read(buf)**
conn.Write([]byte(fmt.Sprintf("收到来自你的%d字节数据", n)))
}
并发服务器
- 创建 监听套接字
listener := net.Listen("tcp", 服务器的IP+port)- 同时注册关闭
defer listener.Close()
- 同时注册关闭
- for 循环 阻塞监听 客户端连接事件
conn := listener.Accept() - 创建 go程 对应每一个 客户端进行数据通信
go HandlerConnet() - 实现
HandlerConnet(conn net.Conn)- defer conn.Close()
- 获取成功连接的客户端 Addr conn.RemoteAddr()
- for 循环 读取 客户端发送数据 conn.Read(buf)
- 处理数据
- 回写转化后的数据 conn.Write(buf[:n])
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:8090")
//err..
defer listener.Close()
fmt.Println("服务器已启动,正在监听....")
for {
conn, err := listener.Accept()
//err..
go handleCon(conn)
}
}
func handleCon(conn net.Conn) {
defer conn.Close()
addr := conn.RemoteAddr()
fmt.Println(addr, " 连接成功")
buf := make([]byte, 4096)
for {
n, err := conn.Read(buf)
if n == 0 {
fmt.Println("对方已关闭连接")
return
}
//err..
fmt.Println("收到来自:", addr, ":", string(buf[:n]))
conn.Write([]byte(fmt.Sprintf("收到来自你的%d字节数据\n", n)))
}
}
判断对端关闭
- Read读客户端/服务器,返回 0
- 注意发送数据时末尾自带的
'\n'
客户端
conn, err := net.Dial("tcp", 服务器的IP+port)- 写数据给 服务器
conn.Write() - 读取服务器回发的 数据
conn.Read() conn.Close()
func main() {
conn, err := net.Dial("tcp", "127.0.0.1:8989")
if err != nil {
fmt.Println("net.Dial err:", err)
return
}
defer conn.Close()
buf := make([]byte, 4096)
conn.Write([]byte("你好,服务器"))
conn.Read(buf)
fmt.Println("读到来自服务器的消息:", string(buf))
}
文件传输案例
发送端(客户端)
- 获取绝对文件名
filepath - 使用
os.Stat()获取文件属性,得到纯文件名 fileName - 主动发起连接服务器请求,结束时关闭连接。
- 发送文件名到接收端
conn.Write() - 读取接收端回发的确认数据
conn.Read() - 判断是否为“ok”。如果是,封装函数 SendFile() 发送文件内容。传参 filePath 和 conn
- 只读 Open 文件, 结束时Close文件
- 循环读本地文件,读到 EOF,读取完毕。
- 将读到的内容原封不动 conn.Write 给接收端(服务器)
接收端(服务器)
- 创建监听 listener,程序结束时关闭。
- 阻塞等待客户端连接 conn,程序结束时关闭conn。
- 读取客户端发送文件名。保存 fileName。
- 回发“ok”。
- 封装函数 RecvFile 接收客户端发送的文件内容。传参 fileName 和 conn
- 按文件名 Create 文件,结束时 Close
- 循环 Read 发送端网络文件内容,当读到 0 说明文件读取完毕。
- 将读到的内容原封不动Write到创建的文件中