[go]socket编程
Posted iiiiiher
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[go]socket编程相关的知识,希望对你有一定的参考价值。
socket特性
- 总是成对出现
- 是全双工的(同时支持收发)(两个channel绑在一起)
应用程序
- cs模式(客户端开发)
- bs模式(web开发)
net包api基础
都是客户端主动发数据(client request)
一共有3个soket。用于通信的有2个。另一个用于监听ip端口
// 服务端
import (
"net"
)
listener, err := net.Listen("tcp", "127.0.0.1:8000") //生成监听socket
defer listener.Close()
conn, err := listener.Accept() //[**阻塞] 生成读写socket
defer conn.Close()
buf := make([]byte, 4096)
n, err := conn.Read(buf) //[**阻塞]
//读客户端数据(client request)
conn.Write(buf[:n]) //写数据给客户端
//客户端
conn, err := net.Dial("tcp", "127.0.0.1:8000")
defer conn.Close()
conn.Write([]byte("Are you Ready?")) //写数据
buf := make([]byte, 4096) //读数据
n, err := conn.Read(buf)
fmt.Println("服务器回发:", string(buf[:n]))
实现conn复用: 循环读写
//server
func main() {
listener, _ := net.Listen("tcp", ":3000")
defer listener.Close()
conn, _ := listener.Accept()
defer conn.Close()
buf := make([]byte, 1024)
for {
n, _ := conn.Read(buf)
if n==0{ //客户端关闭时候server退出
return
}
fmt.Println(string(buf[:n]))
conn.Write([]byte("i am server"))
time.Sleep(time.Second / 3)
}
}
// client
func main() {
conn, _ := net.Dial("tcp", ":3000")
defer conn.Close()
buf := make([]byte, 1024)
for {
conn.Write([]byte("hi server"))
n, _ := conn.Read(buf)
fmt.Println(string(buf[:n]))
time.Sleep(time.Second/3)
}
}
server支持并发
// server
func main() {
listener, _ := net.Listen("tcp", ":3000")
defer listener.Close()
for {
conn, _ := listener.Accept()
go func(conn net.Conn) {
defer conn.Close()
buf := make([]byte, 1024)
for {
n, _ := conn.Read(buf) //已关闭的chan中往出读数据会一直读出零值
if n == 0 {
return
}
fmt.Println(string(buf[:n]))
conn.Write([]byte("i am server"))
time.Sleep(time.Second / 3)
}
}(conn)
}
time.Sleep(time.Second * 1000)
}
//client
func main() {
conn, _ := net.Dial("tcp", ":3000")
defer conn.Close()
buf := make([]byte, 1024)
for {
conn.Write([]byte("hi server"))
n, _ := conn.Read(buf)
fmt.Println(string(buf[:n]))
time.Sleep(time.Second/3)
}
}
server并发-处理退出等.问题
// 并发版的server: 复用lisntner.Accept
listener, err := net.Listen("tcp", "localhost:3000")
defer listener.Close()
for {
conn, err := listener.Accept() //阻塞,获取读写socket: conn
if err != nil {
fmt.Println("listener.Accept err:", err)
return
}
go HandlerConnect(conn)
}
func HandlerConnect(conn net.Conn) {
defer conn.Close()
// 获取连接的客户端 Addr
addr := conn.RemoteAddr()
fmt.Println(addr, "客户端成功连接!")
// 循环读取客户端发送数据
buf := make([]byte, 4096)
for {
n, err := conn.Read(buf)
if "exit
" == string(buf[:n]) || "exit
" == string(buf[:n]) {
fmt.Println("服务器接收的客户端退出请求,服务器关闭")
return
}
if n == 0 {
fmt.Println("服务器检测到客户端已关闭,断开连接!!!")
return
}
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("服务器读到数据:", string(buf[:n]))
conn.Write([]byte(strings.ToUpper(string(buf[:n]))))
}
}
//并发版的客户端
func main() {
conn, err := net.Dial("tcp", "192.168.15.78:8001")
if err != nil {
fmt.Println("net.Dial err:", err)
return
}
defer conn.Close()
// 获取用户键盘输入( stdin ),将输入数据发送给服务器
go func() {
str := make([]byte, 4096)
for {
n, err := os.Stdin.Read(str)
if err != nil {
fmt.Println("os.Stdin.Read err:", err)
continue
}
//写给服务器, 读多少,写多少!
conn.Write(str[:n])
}
}()
// 回显服务器回发的大写数据
buf := make([]byte, 4096)
for {
n, err := conn.Read(buf)
if n == 0 {
fmt.Println("检查到服务器关闭,客户端也关闭")
return
}
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("客户端读到服务器回发:", string(buf[:n]))
}
}
以上是关于[go]socket编程的主要内容,如果未能解决你的问题,请参考以下文章