我一直在为此苦苦挣扎,找不到我的代码无法从我也编写的 TCP 服务器正确读取的原因。我正在使用TcpClient
该类及其GetStream()
方法,但有些东西没有按预期工作。要么操作无限期阻塞(最后一次读取操作没有按预期超时),要么数据被裁剪(由于某种原因,读取操作返回 0 并退出循环,可能服务器响应速度不够快)。这是实现此功能的三种尝试:
// this will break from the loop without getting the entire 4804 bytes from the server
string SendCmd(string cmd, string ip, int port)
{
var client = new TcpClient(ip, port);
var data = Encoding.GetEncoding(1252).GetBytes(cmd);
var stm = client.GetStream();
stm.Write(data, 0, data.Length);
byte[] resp = new byte[2048];
var memStream = new MemoryStream();
int bytes = stm.Read(resp, 0, resp.Length);
while (bytes > 0)
{
memStream.Write(resp, 0, bytes);
bytes = 0;
if (stm.DataAvailable)
bytes = stm.Read(resp, 0, resp.Length);
}
return Encoding.GetEncoding(1252).GetString(memStream.ToArray());
}
// this will block forever. It reads everything but freezes when data is exhausted
string SendCmd(string cmd, string ip, int port)
{
var client = new TcpClient(ip, port);
var data = Encoding.GetEncoding(1252).GetBytes(cmd);
var stm = client.GetStream();
stm.Write(data, 0, data.Length);
byte[] resp = new byte[2048];
var memStream = new MemoryStream();
int bytes = stm.Read(resp, 0, resp.Length);
while (bytes > 0)
{
memStream.Write(resp, 0, bytes);
bytes = stm.Read(resp, 0, resp.Length);
}
return Encoding.GetEncoding(1252).GetString(memStream.ToArray());
}
// inserting a sleep inside the loop will make everything work perfectly
string SendCmd(string cmd, string ip, int port)
{
var client = new TcpClient(ip, port);
var data = Encoding.GetEncoding(1252).GetBytes(cmd);
var stm = client.GetStream();
stm.Write(data, 0, data.Length);
byte[] resp = new byte[2048];
var memStream = new MemoryStream();
int bytes = stm.Read(resp, 0, resp.Length);
while (bytes > 0)
{
memStream.Write(resp, 0, bytes);
Thread.Sleep(20);
bytes = 0;
if (stm.DataAvailable)
bytes = stm.Read(resp, 0, resp.Length);
}
return Encoding.GetEncoding(1252).GetString(memStream.ToArray());
}
最后一个“有效”,但考虑到套接字已经支持读取超时,将硬编码的睡眠放入循环中肯定看起来很难看!我需要在 的 上设置一些属性TcpClient
吗NetworkStream
?问题是否存在于服务器上?服务器不会关闭连接,这取决于客户端。以上也在UI线程上下文(测试程序)中运行,可能与此有关...
有人知道如何正确使用NetworkStream.Read
来读取数据,直到没有更多数据可用?我想我想要的是像旧的 Win32 winsock 超时属性......ReadTimeout
等。它会尝试读取直到达到超时,然后返回 0......但它有时似乎在数据应该返回 0可用(或在途中.. 如果可用,Read 可以返回 0 吗?)然后当数据不可用时,它会在最后一次读取时无限期地阻塞......
是的,我不知所措!