TcpClient/NetworkStream 在同一实例上同时读写
TcpClient/NetworkStream read write simoultanously on same instance
我需要与一个只接受 1 个 TCP 连接的硬件进行通信。但是我找不到任何好的例子,其中相同的 NetworkStream
用于同时读取和写入。
MSDN documentation 表示如下:
Read and write operations can be performed simultaneously on an
instance of the NetworkStream class without the need for
synchronization. As long as there is one unique thread for the write
operations and one unique thread for the read operations, there will
be no cross-interference between read and write threads and no
synchronization is required.
但是,我找不到一个示例来说明如何在不同的线程中使用 NetworkStream
的相同实例进行读写。
我不确定我是否应该:
- 直接用
NetworkStream
读myNetworkStream.ReadAsync()
,或者用StreamReader
,
- 直接用
NetworkStream
写myNetworkStream.WriteAsync()
,或者用StreamWriter
,
- 在实例化
TcpClient
、 时直接启动一个带有while(true)
的新线程用于读取
- 保留对我的
NetworkStream
实例的全局引用,以便我可以随时编写...
在 TCP connections/network 通信方面,我远不是专家,所以肯定有一些我不完全理解的事情...
提前致谢:)
记住I/O绑定任务,there is no thread。
您发布的段落并未真正处理任务,例如:
var client = new TcpClient();
await client.ConnectAsync("example.com", 80);
var stream = client.GetStream();
// start reading from the socket
var rBuf = new byte[2048];
var tRecv = stream.ReadAsync(rBuf, 0, rBuf.Length);
// send data and wait for it to complete
var sBuf = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n");
await stream.WriteAsync(sBuf, 0, sBuf.Length);
// now await for the data
var bytesRecv = await tRecv;
Console.WriteLine($"Received {bytesRecv} bytes");
在处理底层流时,不会有两个并发线程同时做某事。
该段所说的是做这样的事情:
var client = new TcpClient();
await client.ConnectAsync("example.com", 80);
var stream = client.GetStream();
new Thread(() =>
{
var rBuf = new byte[2048];
var bytesRecv = stream.Read(rBuf, 0, rBuf.Length);
Console.WriteLine($"Received {bytesRecv} bytes");
}).Start();
Thread.Sleep(500); // ensure the above thread has started
new Thread(() =>
{
var sBuf = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n");
stream.Write(sBuf, 0, sBuf.Length);
}).Start();
Console.ReadKey(true);
在上面的示例中,您有两个不同的线程,它们同时对底层流执行某些操作,并且没有任何“崩溃”。
至于你应该使用什么模式......你有几种可能性。您在上面的第一个示例中使用了任务(现代方法),或者您可以使用阻塞调用(“old-school”方法)执行线程化 while(true)
方法。或者 Begin...
和 End...
方法(介于 old-school 和现代之间)。
什么最好?你选。我个人喜欢在数据可用时触发事件,所以我倾向于使用 BeginConnect
/EndConnect
、BeginReceive
/EndReceive
等方法。
尽管有时,我喜欢使用 ReadAsync()
执行 while(true)
,但使用 CancellationToken
来终止循环。
我不建议使用while(true)
来阻止调用。有了 TPL 为我们提供的出色工具,我们不必再启动通用线程来完成任何事情。
我需要与一个只接受 1 个 TCP 连接的硬件进行通信。但是我找不到任何好的例子,其中相同的 NetworkStream
用于同时读取和写入。
MSDN documentation 表示如下:
Read and write operations can be performed simultaneously on an instance of the NetworkStream class without the need for synchronization. As long as there is one unique thread for the write operations and one unique thread for the read operations, there will be no cross-interference between read and write threads and no synchronization is required.
但是,我找不到一个示例来说明如何在不同的线程中使用 NetworkStream
的相同实例进行读写。
我不确定我是否应该:
- 直接用
NetworkStream
读myNetworkStream.ReadAsync()
,或者用StreamReader
, - 直接用
NetworkStream
写myNetworkStream.WriteAsync()
,或者用StreamWriter
, - 在实例化
TcpClient
、 时直接启动一个带有 - 保留对我的
NetworkStream
实例的全局引用,以便我可以随时编写...
while(true)
的新线程用于读取
在 TCP connections/network 通信方面,我远不是专家,所以肯定有一些我不完全理解的事情...
提前致谢:)
记住I/O绑定任务,there is no thread。
您发布的段落并未真正处理任务,例如:
var client = new TcpClient();
await client.ConnectAsync("example.com", 80);
var stream = client.GetStream();
// start reading from the socket
var rBuf = new byte[2048];
var tRecv = stream.ReadAsync(rBuf, 0, rBuf.Length);
// send data and wait for it to complete
var sBuf = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n");
await stream.WriteAsync(sBuf, 0, sBuf.Length);
// now await for the data
var bytesRecv = await tRecv;
Console.WriteLine($"Received {bytesRecv} bytes");
在处理底层流时,不会有两个并发线程同时做某事。
该段所说的是做这样的事情:
var client = new TcpClient();
await client.ConnectAsync("example.com", 80);
var stream = client.GetStream();
new Thread(() =>
{
var rBuf = new byte[2048];
var bytesRecv = stream.Read(rBuf, 0, rBuf.Length);
Console.WriteLine($"Received {bytesRecv} bytes");
}).Start();
Thread.Sleep(500); // ensure the above thread has started
new Thread(() =>
{
var sBuf = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\nHost: example.com\r\n\r\n");
stream.Write(sBuf, 0, sBuf.Length);
}).Start();
Console.ReadKey(true);
在上面的示例中,您有两个不同的线程,它们同时对底层流执行某些操作,并且没有任何“崩溃”。
至于你应该使用什么模式......你有几种可能性。您在上面的第一个示例中使用了任务(现代方法),或者您可以使用阻塞调用(“old-school”方法)执行线程化 while(true)
方法。或者 Begin...
和 End...
方法(介于 old-school 和现代之间)。
什么最好?你选。我个人喜欢在数据可用时触发事件,所以我倾向于使用 BeginConnect
/EndConnect
、BeginReceive
/EndReceive
等方法。
尽管有时,我喜欢使用 ReadAsync()
执行 while(true)
,但使用 CancellationToken
来终止循环。
我不建议使用while(true)
来阻止调用。有了 TPL 为我们提供的出色工具,我们不必再启动通用线程来完成任何事情。