Server端常用函数、接口:
Listen函数:
func Listen(network, address string) (Listener, error)
network:选用的协议:TCP、UDP, 如:“tcp”或 “udp”
address:IP地址+端口号, 如:“127.0.0.1:8000”或 “:8000”
Listener 接口:
type Listener interface {
Accept() (Conn, error)
Close() error
Addr() Addr
}
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
}
TCP-服务端实现:
func main() {
// 指定服务器的通讯协议、ip、端口,Listen本身不做监听,这一步是创建了一个用于监听的Socket
listen, err := net.Listen("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("net.Listen出错:", err)
return
}
defer listen.Close()
fmt.Println("服务器启动完毕,等待客户端连接")
// 阻塞监听客户端连接请求,成功建立连接后会返回用于通信的Socket
accept, err := listen.Accept()
if err != nil {
fmt.Println("listen.Accept出错:", err)
return
}
defer accept.Close()
fmt.Println("服务器与客户端连接成功")
// 读取客户端发动的请求
buf := make([]byte, 4096)
read, err := accept.Read(buf)
if err != nil {
fmt.Println("accept.Read出错:", err)
return
}
// 接收数据后处理数据
fmt.Println("服务器获取到:", string(buf[:read]))
}
Mac可以通过netcat进行测试:
TCP-客户端实现:
func main() {
// 指定用户端的通讯协议、ip、端口,Listen本身不做监听,这一步是创建了一个用于监听的Socket
dial, err := net.Dial("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("net.Dial出错:", err)
return
}
defer dial.Close()
// 发送数据
dial.Write([]byte("我是客户端"))
// 接收服务器返回的数据
buf := make([]byte, 4096)
read, err := dial.Read(buf)
if err != nil {
fmt.Println("accept.Read出错:", err)
return
}
// 接收数据后处理数据
fmt.Println("客户端获取到:", string(buf[:read]))
}
TCP实现并发-服务器:
上面都是单机版的客户端通信,如果想要实现并发,需要使用Goroutine+循环实现
循环读取客户端发送的数据如果客户端强制关闭连接需要做处理客户端发送exit时
演示:
package main
import (
"fmt"
"net"
"strings"
)
func main() {
// 创建监听套接字
listen, err := net.Listen("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("net.Listen出错:", err)
return
}
defer listen.Close()
// 创建客户端连接请求
fmt.Println("服务器启动成功,等待客户端连接!")
for {
accept, err := listen.Accept()
if err != nil {
fmt.Println("listen.Accept出错:", err)
return
}
// 调用服务器和客户端通信的函数
go HandlerConnect(accept)
}
}
func HandlerConnect(accept net.Conn) {
defer accept.Close()
// 获取客户端发送的数据
// 获取连接客户端的网络地址
addr := accept.RemoteAddr()
fmt.Println(addr, "客户端连接成功!")
buf := make([]byte, 4096)
for {
read, err := accept.Read(buf)
if err != nil {
fmt.Println("accept.Read出错:", err)
return
}
fmt.Println("服务器读到数据:", string(buf[:read]))
// 模拟服务器收到数据后,回发给客户端,小写转大写
data := strings.ToUpper(string(buf[:read]))
accept.Write([]byte(data))
}
}
TCP实现并发-客户端:
演示:
package main
import (
"fmt"
"net"
"os"
)
func main() {
//主动发送连接请求
dial, err := net.Dial("tcp", "127.0.0.1:8000")
if err != nil {
fmt.Println("et.Dial出错了", err)
return
}
defer dial.Close()
// os.Stdin():获取用户键盘录入,
go func() {
str := make([]byte, 4096)
for {
read, err := os.Stdin.Read(str)
if err != nil {
fmt.Println("os.Stdin.Read出错了", err)
continue
}
// 读到的数据写给服务器,读多少写多少
dial.Write(str[:read])
}
}()
buf := make([]byte, 4096)
// 回显服务器发送的数据,转成大写
for {
read, err := dial.Read(buf)
// read=0的说明对端关闭连接,如果关闭连接这里就不需要往下读数据了
if read == 0 {
fmt.Println("检测到服务端端已经断开连接!")
return
}
if err != nil {
fmt.Println("回显服务器发送的数据dial.Read出错了", err)
return
}
fmt.Println("客户端读到服务器的回显数据", string(buf[:read]))
}
}
UDP实现并发-服务器:
由于UDP是“无连接”的,所以,服务器端不需要额外创建监听套接字,只需要指定好IP和port,然后监听该地址,等待客户端与之建立连接,即可通信。
创建监听地址:
func ResolveUDPAddr(network, address string) (*UDPAddr, error)
创建监听连接:
func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error)
接收udp数据:
func (c *UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error)
写出数据到udp:
func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error)
演示:
package main
import (
"fmt"
"net"
)
func main() {
// 指定服务器的ip和端口,和TCP协议不一样,需要先写好再传给ListenUDP使用
ServerAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:8000")
if err != nil {
fmt.Println("net.ResolveUDPAddr err:", err)
return
}
fmt.Println("服务器启动成功!")
// 创建用户通信的Socket
udpConnect, err := net.ListenUDP("udp", ServerAddr)
if err != nil {
fmt.Println("net.ListenUDP err:", err)
return
}
defer udpConnect.Close()
fmt.Println("服务器创建Socket成功!")
// 读写客户端的数据
buf := make([]byte, 4096)
count := 0
for {
// 返回值:n int(读到的字节数), addr *UDPAddr(客户端的地址), err error
udpBytes, ConnectAddr, err := udpConnect.ReadFromUDP(buf)
if err != nil {
fmt.Println("udpConnect.ReadFromUDP err:", err)
return
}
count++
// 模拟处理数据
fmt.Printf("服务器读到第%v条数据 %v :%s\n", count, ConnectAddr, string(buf[:udpBytes]))
go func() {
// 回写数据到客户端
udpConnect.WriteToUDP([]byte("回写数据到客户端\n"), ConnectAddr)
}()
}
}
UDP实现并发-客户端:
package main
import (
"fmt"
"net"
"time"
)
func main() {
dial, err := net.Dial("udp", "127.0.0.1:8000")
if err != nil {
fmt.Println("net.Dial出错:", err)
return
}
defer dial.Close()
for {
// 发送数据
dial.Write([]byte("我是客户端"))
// 接收服务器返回的数据
buf := make([]byte, 4096)
read, err := dial.Read(buf)
if err != nil {
fmt.Println("accept.Read出错:", err)
return
}
// 接收数据后处理数据
fmt.Println("客户端获取到:", string(buf[:read]))
time.Sleep(time.Second)
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)