一、Socket
socket编程对应OSI七层网络模型的传输层,定义传输数据的协议端口号,以及流控和差错校验。协议有:TCP UDP。
1、TCP Socket
客户端编码
package main
import (
"fmt"
"log"
"net"
)
func main() {
// 使用tcp协议拨号服务器127.0.0.1:8080
conn, err := net.Dial("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
// 向服务器端写数据
n, err := conn.Write([]byte("hello"))
if err != nil {
log.Fatal(err)
}
fmt.Printf("send %d byte to server\n", n)
receive := make([]byte, 5)
// 接受服务器端数据
_, err = conn.Read(receive)
if err != nil {
log.Fatal(err)
}
fmt.Printf("receive from server %s", string(receive))
}
服务端编码
package main
import (
"fmt"
"log"
"net"
)
func main() {
// tcp协议监听本地8080端口
listener, err := net.Listen("tcp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
for {
// 阻塞等待客户端连接
conn, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
// 开启一个协程处理客户端请求
go workGoroutine(conn)
}
}
func workGoroutine(conn net.Conn) {
fmt.Println(conn.RemoteAddr().String())
receive := make([]byte, 5)
conn.Read(receive)
fmt.Printf("receive from client %s\n", string(receive))
conn.Write([]byte("world"))
}
2、UDP Socket
客户端编码
package main
import (
"fmt"
"log"
"net"
)
func main() {
conn, err := net.Dial("udp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
n, err := conn.Write([]byte("hello"))
if err != nil {
log.Fatal(err)
}
fmt.Printf("send %d byte to server\n", n)
receive := make([]byte, 5)
_, err = conn.Read(receive)
if err != nil {
log.Fatal(err)
}
fmt.Printf("receive from server %s", string(receive))
}
服务端编码
package main
import (
"fmt"
"log"
"net"
"time"
)
func main() {
laddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
conn, err := net.ListenUDP("udp", laddr)
if err != nil {
log.Fatal(err)
}
workGoroutine(conn)
time.Sleep(3 * time.Second)
}
func workGoroutine(conn *net.UDPConn) {
receive := make([]byte, 5)
_, addr, err := conn.ReadFromUDP(receive)
if err != nil {
log.Fatal(err)
}
fmt.Printf("receive from client %s\n", string(receive))
conn.WriteToUDP([]byte("world"), addr)
}
二、webSocket
webSocket是基于tcp的一种网络传输协议,位于OSI模型的应用层。
客户端编码
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>webSocket</title>
<script type="text/javascript">
var ws;
if ("WebSocket" in window)
{
ws = new WebSocket("ws://localhost:8080/ws");
ws.onopen = function()
{
alert("你已上线");
};
ws.onmessage = function (evt)
{
msg = evt.data;
alert(msg);
};
ws.onclose = function()
{
alert("你已下线...");
};
}
else
{
alert("浏览器不支持 WebSocket!");
}
function send(){
if(!ws) {
alert("浏览器不支持 WebSocket!")
} else {
msg = document.getElementById("msgtxt").value
ws.send(msg)
}
}
</script>
</head>
<body>
<input type="text" id="msgtxt"><br><br>
<button onclick="send()" >发送</button>
</body>
</html>
服务器端编码
服务端使用github.com/gorilla/websocket websocket 库,没有采用go官方 golang.org/x/net/websocket
package main
import (
"html/template"
"log"
"net/http"
"github.com/gorilla/websocket"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("home.html")
t.Execute(w, nil)
})
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
up := websocket.Upgrader{
}
conn, err := up.Upgrade(w, r, nil)
if err != nil {
log.Fatal(err)
}
for {
_, message, err := conn.ReadMessage()
if err != nil {
log.Fatal(err)
}
msgTxt := string(message)
if msgTxt == "bye" {
conn.Close()
return
}
log.Printf("接受到客户端消息:%s\n", msgTxt)
messageSlice := []byte("我是服务器收到了你的信息:")
messageSlice = append(messageSlice, message...)
conn.WriteMessage(websocket.TextMessage, messageSlice)
}
})
http.ListenAndServe(":8080", nil)
}