我有TCP服务器,什么接收大数据不间断。 我需要向许多客户广播此流。
更新 我需要播放视频流。也许有现成的解决方案?
答案 0 :(得分:2)
如果您想异步执行此操作,则可以利用System.Threading.Tasks
namespace。
首先,您需要Stream
个Task
个实例的地图,可以等待完成:
IDictionary<Stream, Task> streamToTaskMap = outputStreams.
ToDictionary(s => s, Task.Factory.StartNew(() => { });
上面有一点点开销,因为有一个浪费的Task
实例什么都不做,但考虑到你需要执行的Task
个实例和延续的数量,这个价格很小。
从那里,您将从流中读取内容,然后异步地将其写入每个Stream
实例:
byte[] buffer = new byte[<buffer size>];
int read = 0;
while ((read = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
// The buffer to copy into.
byte[] copy = new byte[read];
// Perform the copy.
Array.Copy(buffer, copy, read);
// Cycle through the map, and replace the task with a continuation
// on the task.
foreach (Stream stream in streamToTaskMap.Keys)
{
// Continue.
streaToTaskMap[stream] = streaToTaskMap[stream].ContinueWith(t => {
// Write the bytes from the copy.
stream.Write(copy, 0, copy.Length);
});
}
}
最后,您可以通过调用
等待写入的所有流Task.WaitAll(streamToTaskMap.Values.ToArray());
有几点需要注意。
首先,由于传递给ContinueWith
的lambda,需要buffer
的副本; lambda是一个封装buffer
的闭包,因为它是异步处理的,所以内容可能会改变。每个连续性都需要自己的缓冲区副本才能读取。
这也是对Stream.Write
的调用使用Array.Length
属性的原因;否则,必须在循环的每次迭代中复制read
变量。
此外,能够在Stream
类上使用BeginWrite
/ EndWrite
方法更为理想;因为没有ContinueWithAsync
方法将采用Task
并继续使用异步方法,所以调用异步版本的读取没有任何好处。
这是其中一种情况,可能最好自己调用BeginWrite / EndWrite(以及BeginRead
/ EndRead
),以便充分利用异步操作;当然,这会有点复杂,因为你不会对Task
提供的操作结果进行封装,如果你使用匿名的话,你必须对buffer
采取相同的预防措施。方法/闭包。
答案 1 :(得分:1)
生成一个将流传递给它的线程,以及要写入
的流byte[] buffer = new byte[BUFFER_SIZE];
int btsRead = 0;
while ((btsRead = inputStream.Read(buffer, 0, BUFFER_SIZE)) > 0)
{
foreach (Stream oStream in outputStreams)
oStream.Write(buffer, 0, btsRead);
}
编辑:并行化写入:
用以下内容替换foreach chunk:
Parallel.ForEach(outputStreams, oStream =>
{
oStream.Write(buffer, 0, btsRead);
});
答案 2 :(得分:0)
基本上,您想要线程化您的应用程序。这是一个线程和TCP / IP
的简单示例C# Tutorial - Simple Threaded TCP Server | Switch on the Code