我正在尝试为golang中的视频流编写缓存代理。
我的问题是,如何在多个连接之间分配大数据流的流副本?
或者如何存储(缓存)并安全(快速)访问来自多个goroutine的数据?
我尝试了带有互斥和通道的几个选项,但是它们没有用。这是一些有错误的示例。
这是简化版:
...
var clients []*client
func new_client(conn net.Conn) {
client := &client{
conn: conn,
}
clients = append(clients, client)
}
...
func stream(source io.Reader) {
buf := make([]byte, 32*1024)
for {
n, _ := source.Read(buf)
for _, client := range clients {
wn, e := client.conn.Write(buf[0:n])
// blocks here for all clients if one of clients stops reading
}
}
}
此版本的问题是当一个客户端停止读取但没有关闭连接时,对Write()的调用开始阻塞。在goroutine中对Write()的包装调用(客户端上具有互斥锁)没有帮助-与通道(下一个示例)存在相同的延迟,此外go不能保证goroutine的执行顺序。
我试图这样修复它:
for _, client := range clients {
client.conn.SetWriteDeadline(time.Now().Add(1 * time.Millisecond))
wn, e := client.conn.Write(buf[0:n])
}
它有助于阻止,但速度较慢的客户端无法及时读取,从而增加了超时-返回延迟。
我也尝试过这样的事情:
...
var clients []*client
func new_client(conn net.Conn) {
client := &client{
buf_chan: make(chan []byte, 100),
}
clients = append(clients, client)
for {
buf <- client.buf_chan
n, e := client.conn.Write(buf)
}
}
...
func stream(source io.Reader) {
buf := make([]byte, 32*1024)
for {
n, _ := source.Read(buf)
for _, client := range clients {
client.buf_chan <- buf[0:n]
}
}
}
但是在此版本中,发送到频道和另一端接收之间存在一些延迟,因此播放器中的视频流开始出现延迟,延迟。
也许是关于打包的建议,还是这类任务的设计模式?
感谢您的帮助!
[在频道版本中,缓慢的客户端也会增加延迟。由于慢速客户端可以使其buf_chan变满,因此将阻止对其buf_chan的写入。选择Wrappper可以避免它:
select {
case client.buf_chan <- buf[0:n]:
default:
//handle slow client ...
}
我需要代码源golang完成!
http.Get(url live video) read one source write to pipenamed after send to multiple clients connection
f, err := os.OpenFile(pipenamed, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0777)
.......
read pipenamed after send to multiple connection
after remove connection closed
感谢您的帮助!