用Go语言实现Socket网络编程
基于C/S开发模型
实现客户端与服务端之间的通信
客户端发送消息给服务端
服务端进行业务处理
服务端将处理好的数据返回给客户端
基础版服务端只能同时服务一个客户端
且只进行一次通话(收发消息)
客户端
客户端开发代码如下
package main
import (
"fmt"
"net"//Socket编程使用的包 需要引入
)
func main() {
//与服务器建立连接
//参数1表示使用TCP协议
//参数2是"127.0.0.1:666"的省略写法
//如果IP地址是本地回环IP 可以省略冒号之前的内容
conn, err := net.Dial("tcp", ":666")
//err == nil 时表示没有错误
if err != nil {
fmt.Println("net.Dial err:", err)
return
}
fmt.Println("Dial success")
//发送的数据是字符切片的格式
sendData := []byte("hello")
//向服务器发送数据
cnt, err := conn.Write(sendData)
if err != nil {
fmt.Println("conn.Write err:", err)
return
}
fmt.Println("Client to Server...")
fmt.Println("length:", cnt, "data", string(sendData))
//接收服务器返回的数据
buf := make([]byte, 1024)
cnt, err = conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("Server to Client...")
fmt.Println("length:", cnt, "data", string(buf[:cnt])) //只处理前cnt个字符
//关闭连接
conn.Close()
}
服务端
服务端开发代码如下
package main
import (
"fmt"
"net"
"strings"
)
func main() {
//创建监听
ip := "127.0.0.1"
port := 666
//.Sprintf函数往address变量中写入IP和端口信息
address := fmt.Sprintf("%s:%d", ip, port)
//开始监听 选择TCP协议 和 监听的方向
listener, err := net.Listen("tcp", address)
if err != nil {
fmt.Println("net.Listen err:", err)
return
}
//提取连接
conn, err := listener.Accept()
if err != nil {
fmt.Println("listener.Accept err:", err)
return
}
fmt.Println("Accept success")
//创建容器用于接收读取到的数据
buf := make([]byte, 1024) //使用make函数创建切片
//cnt是实际读到的字符数
cnt, err := conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("Client to Server...")
fmt.Println("length:", cnt, "data", string(buf))
//服务器业务实现 小写转成大写
upperData := strings.ToUpper(string(buf[:cnt])) //只处理前cnt个字符
cnt, err = conn.Write([]byte(upperData))
fmt.Println("Server to Client...")
fmt.Println("length:", cnt, "data", upperData)
//关闭连接
conn.Close()
}
效果展示
使用GoLand开发
效果截图如下
服务端可以同时服务多个客户端
并且每个客户端可以实现多次收发数据
核心思想
主GO程负责监听处理连接
子GO程负责处理数据 实现客户端与服务端互动的具体逻辑
客户端
客户端开发代码如下
package main
import (
"fmt"
"net"
"time"
)
func main() {
//与服务器建立连接
conn, err := net.Dial("tcp", ":666")
if err != nil {
fmt.Println("net.Dial err:", err)
return
}
fmt.Println("Dial success")
//client0发送的内容是 "hello this is client 0"
//client1发送的内容是 "hello this is client 1"
sendData := []byte("hello this is client 0")
//向服务器多次发送数据
for {
cnt, err := conn.Write(sendData)
if err != nil {
fmt.Println("conn.Write err:", err)
return
}
fmt.Println("send data to server...")
//接收服务器返回的数据
buf := make([]byte, 1024)
cnt, err = conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("Server to Client...")
fmt.Println("length:", cnt, "data", string(buf[:cnt])) //只处理前cnt个字符
//休息5秒再发送
time.Sleep(5 * time.Second)
}
}
服务端
服务端开发代码如下
package main
import (
"fmt"
"net"
"strings"
)
//业务处理函数需要接收conn参数 对应一个具体的客户端方向
func handle(conn net.Conn) {
for {
//创建容器用于接收读取到的数据
buf := make([]byte, 1024) //使用make创建切片
//cnt是实际读到的字符数
cnt, err := conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}
fmt.Println("Client to Server...")
fmt.Println("length:", cnt, "data", string(buf))
//服务器业务 小写转成大写
upperData := strings.ToUpper(string(buf[:cnt])) //只处理前cnt个字符
cnt, err = conn.Write([]byte(upperData))
fmt.Println("Server to Client...")
fmt.Println("length:", cnt, "data", upperData)
}
}
func main() {
//创建监听
ip := "127.0.0.1"
port := 666
address := fmt.Sprintf("%s:%d", ip, port)
listener, err := net.Listen("tcp", address)
if err != nil {
fmt.Println("net.Listen err:", err)
return
}
//主GO程负责监听处理连接
//子GO程负责处理数据 实现客户端与服务端互动的具体逻辑
//主GO程提取多个连接
for {
fmt.Println("listening...")
conn, err := listener.Accept()
if err != nil {
fmt.Println("listener.Accept err:", err)
return
}
fmt.Println("Accept success!")
//启动一个子GO程 执行业务处理函数
go handle(conn)
}
}
效果展示
使用GoLand开发
效果截图如下
补充
这是socket_client1.go的主函数
上文代码段是socket_client0.go的主函数
func main() { //与服务器建立连接 conn, err := net.Dial("tcp", ":666") if err != nil { fmt.Println("net.Dial err:", err) return } fmt.Println("Dial success") //client0发送的内容是 "hello this is client 0" //client1发送的内容是 "hello this is client 1" sendData := []byte("hello this is client 1") //向服务器多次发送数据 for { cnt, err := conn.Write(sendData) if err != nil { fmt.Println("conn.Write err:", err) return } fmt.Println("send data to server...") //接收服务器返回的数据 buf := make([]byte, 1024) cnt, err = conn.Read(buf) if err != nil { fmt.Println("conn.Read err:", err) return } fmt.Println("Server to Client...") fmt.Println("length:", cnt, "data", string(buf[:cnt])) //只处理前cnt个字符 time.Sleep(5 * time.Second) } }