我一直在努力解决这个问题,但找不到我的代码无法从我也编写的 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
of the NetworkStream
?问题是否出在服务器上?服务器不会关闭连接,这取决于客户端。上面的内容也在UI线程上下文(测试程序)内运行,也许与此有关......
有人知道如何正确使用吗NetworkStream.Read
读取数据直到没有更多数据可用?我想我想要的是旧的 Win32winsock 超时属性之类的东西......ReadTimeout
等等。它尝试读取直到达到超时,然后返回0...但有时当数据应该可用时它似乎返回0(或者在途中..如果可用的话可以读取返回0吗?)并且它然后,当数据不可用时,在最后一次读取时无限期地阻塞...
是的,我很茫然!