我写了一个类,试图读取服务器发送的字节数据,当我的应用程序结束时,我也希望循环结束,但是如果没有数据可用,它会显示NetworkStream.Read()
等待。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Threading.Tasks;
namespace Stream
{
class Program
{
private static TcpClient client = new TcpClient("127.0.0.1", 80);
private static NetworkStream stream = client.GetStream();
static void Main(string[] args)
{
var p = new Program();
p.Run();
}
void Run()
{
ThreadPool.QueueUserWorkItem(x =>
{
while (true)
{
stream.Read(new byte[64], 0, 64);
}
});
client.Close();
// insert Console.ReadLine(); if you want to see an exception occur.
}
}
}
使用此代码,我们得到
System.IO.IOException
说“无法从传输连接读取数据:远程主机强行关闭现有连接”,ObjectDisposedException
说“无法访问已处置的对象”或System.IO.IOException
说“通过调用WSACancelBlockingCall来中断阻塞操作”。 那我怎么能安全地结束这个方法呢?
答案 0 :(得分:5)
这可能会有所帮助
void Run() {
ThreadPool.QueueUserWorkItem(ReadLoop);
}
void ReadLoop(object x) {
if (stream.DataAvailable)
stream.Read(new byte[64], 0, 64);
else
Thread.Sleep(TimeSpan.FromMilliseconds(200));
if (Finished)
client.Close();
else if (!Disposed && !Finished)
ThreadPool.QueueUserWorkItem(ReadLoop);
}
您需要管理Finished& amp;把自己安排在真正的班上。
答案 1 :(得分:5)
从我在运行程序时看到的,第一个例外“无法从传输连接中读取数据......”不是由Stream.Read引发的,而是由TcpClient的构造函数引发的,很可能是由于事实在127.0.0.1:80没有服务器接受连接。
现在,如果你想在Stream.Read上很好地结束,我会异步进行。通过这种方式,您可以捕获在Read和清理程序期间抛出的任何异常。以下是您的程序的修改版本:
using System;
using System.Net.Sockets;
namespace Stream
{
class Program
{
private static TcpClient client;
private static NetworkStream stream;
static void Main(string[] args)
{
var p = new Program();
p.Run();
}
void Run()
{
try
{
client = new TcpClient("127.0.0.1", 80);
stream = client.GetStream();
byte[] buffer = new byte[64];
stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(OnRead), buffer);
client.Close();
Console.ReadKey();
}
catch (Exception)
{
//...
}
}
void OnRead(IAsyncResult result)
{
try
{
stream.EndRead(result);
byte[] buffer = result.AsyncState as byte[];
if (buffer != null)
{
//...
}
// continue to read the next 64 bytes
buffer = new byte[64];
stream.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(OnRead), buffer);
}
catch (Exception)
{
// From here you can get exceptions thrown during the asynchronous read
}
}
}
}
答案 2 :(得分:3)
如果实现了简单的控制台客户端应用程序,那么为什么要使用另一个线程连接并从服务器接收数据?
static void Main(string[] args)
{
var client = new TcpClient("...", ...);
var buffer = new byte[1024];
using (var networkStream = client.GetStream())
{
int bytesRead;
while ((bytesRead = networkStream.Read(buffer, 0, buffer.Length)) > 0)
{
var hexString = BitConverter.ToString(buffer, 0, bytesRead);
Console.WriteLine("Bytes received: {0}", hexString);
}
}
}