Golang实现异步读写TCP服务器
Golang实现异步读写TCP服务器 你好,
我想创建一个能够接收和发送二进制数据的TCP服务器。我希望即使客户端不发送数据,也能向客户端发送数据。我已经尝试了一个使用Go协程来接收和发送数据的测试程序。当客户端断开连接时,一切正常。但当服务器尝试断开客户端连接时,有时会成功。
func main() {
fmt.Println("hello world")
}
1 回复
更多关于Golang实现异步读写TCP服务器的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
以下是一个使用Go语言实现的异步读写TCP服务器示例,支持主动向客户端发送二进制数据:
package main
import (
"fmt"
"net"
"sync"
"time"
)
type Client struct {
conn net.Conn
send chan []byte
}
type Server struct {
clients map[*Client]bool
register chan *Client
unregister chan *Client
broadcast chan []byte
mutex sync.RWMutex
}
func NewServer() *Server {
return &Server{
clients: make(map[*Client]bool),
register: make(chan *Client),
unregister: make(chan *Client),
broadcast: make(chan []byte),
}
}
func (s *Server) Run() {
for {
select {
case client := <-s.register:
s.mutex.Lock()
s.clients[client] = true
s.mutex.Unlock()
fmt.Printf("客户端连接: %v\n", client.conn.RemoteAddr())
case client := <-s.unregister:
s.mutex.Lock()
if _, ok := s.clients[client]; ok {
close(client.send)
client.conn.Close()
delete(s.clients, client)
fmt.Printf("客户端断开: %v\n", client.conn.RemoteAddr())
}
s.mutex.Unlock()
case message := <-s.broadcast:
s.mutex.RLock()
for client := range s.clients {
select {
case client.send <- message:
default:
close(client.send)
delete(s.clients, client)
}
}
s.mutex.RUnlock()
}
}
}
func (s *Server) Start(addr string) error {
listener, err := net.Listen("tcp", addr)
if err != nil {
return err
}
defer listener.Close()
go s.Run()
fmt.Printf("服务器监听: %s\n", addr)
for {
conn, err := listener.Accept()
if err != nil {
fmt.Printf("接受连接错误: %v\n", err)
continue
}
client := &Client{
conn: conn,
send: make(chan []byte, 256),
}
s.register <- client
go s.handleRead(client)
go s.handleWrite(client)
}
}
func (s *Server) handleRead(client *Client) {
defer func() {
s.unregister <- client
}()
buffer := make([]byte, 4096)
for {
n, err := client.conn.Read(buffer)
if err != nil {
return
}
data := buffer[:n]
fmt.Printf("收到来自 %v 的数据: %v\n", client.conn.RemoteAddr(), data)
// 示例:将接收到的数据广播给所有客户端
s.broadcast <- data
}
}
func (s *Server) handleWrite(client *Client) {
defer func() {
s.unregister <- client
}()
for {
select {
case message, ok := <-client.send:
if !ok {
return
}
_, err := client.conn.Write(message)
if err != nil {
return
}
fmt.Printf("发送数据到 %v: %v\n", client.conn.RemoteAddr(), message)
}
}
}
// 示例:主动向所有客户端发送数据
func (s *Server) SendToAll(data []byte) {
s.broadcast <- data
}
// 示例:定时发送心跳包
func (s *Server) StartHeartbeat(interval time.Duration) {
go func() {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for range ticker.C {
heartbeat := []byte{0x01, 0x02, 0x03, 0x04} // 示例心跳数据
s.SendToAll(heartbeat)
}
}()
}
func main() {
server := NewServer()
// 启动心跳机制(每5秒发送一次)
server.StartHeartbeat(5 * time.Second)
// 启动服务器
err := server.Start(":8080")
if err != nil {
fmt.Printf("服务器启动失败: %v\n", err)
}
}
这个实现包含以下关键特性:
- 异步读写分离:每个客户端连接使用独立的goroutine处理读和写操作
- 主动发送能力:通过
SendToAll方法可以随时向所有客户端发送二进制数据 - 连接管理:使用注册/注销机制管理客户端连接
- 线程安全:使用读写锁保护共享数据
- 心跳机制:示例展示了如何定时向客户端发送数据
服务器断开客户端连接的逻辑在unregister通道处理中,确保连接正确关闭和资源释放。

