我正在编写一个tcp网桥,用于将数据从conn传输到另一个conn,该进程是双工的,这意味着另一个conn可能需要将数据写入第一个conn。
我打开四个go-routines来处理任务,每个例程只执行以下操作之一:从上游读取,写入下游,从下游读取,以及写入上游。 read-routine程序很简单:
func readUpstream(conn *net.TCPConn) {
for {
buf := make([]byte, 10)
_, err := io.ReadFull(conn, buf)
if err != nil {
break
}
pipeToDownstream(buf)
}
}
通常,函数pipeToDownload
只需要一个通道写入它,writeDownstream
函数只读取通道,然后将其写入下游conn,如下所示:
func pipeToDownstream(buf) {
downPipe <- buf
}
func writeDownstream(conn *net.Conn) {
for {
data := <- downPipe
_, err := conn.Write(data)
if err != nil {
break
}
}
}
但是,在我的情况下,来自上游的数据是视频流,我需要确保实时管道,这意味着如果下游正在写入,则只保留从上游读取的最后一帧,然后写下游例程从保留数据中读取然后写入它。因为视频流需要大带宽,但有时客户端带宽不足以发送数据,然后写入下游例程将被阻止,然后如果直接使用pipeToDownstream
函数将阻止readUpstream
去例程。
因此,我添加了一个标志来表示writeDownstream
正在写入,如果标志为readUpstream
,则应保留来自1
的读取数据,否则应直接传送到通道。这意味着我需要添加一个互斥锁,以确保flag
和reserved
字段的线程安全。
我该怎么办?