【问题标题】:Why does this code for TcpClient work in vb.net, but not c#?为什么 TcpClient 的这段代码在 vb.net 中有效,但在 c# 中无效?
【发布时间】:2018-05-26 05:38:37
【问题描述】:

这里有一个小实验,我继承并计划重构的代码,但我被一件事难住了。 vb.net 中的那个有效,但c# 中的那个无效。

顺便说一句,BUFFER_SIZE 等于 2048,我知道它有几个问题,但我只能假设我误解了Byte 构造与两种语言之间的相关性:

Dim bytesRcvd As Integer = 0
Dim byteSendBuffer As Byte() = New Byte(BUFFER_SIZE - 1) {}
Dim byteReceiveBuffer As Byte() = New Byte(BUFFER_SIZE - 1) {}
Dim receiveMessage As String = Nothing
byteSendBuffer = Encoding.ASCII.GetBytes(sendMessage)
Dim client As System.Net.Sockets.TcpClient = Nothing
Dim netStream As System.Net.Sockets.NetworkStream = Nothing

client = New System.Net.Sockets.TcpClient("localhost", 9060)

netStream = client.GetStream()

netStream.Write(byteSendBuffer, 0, byteSendBuffer.Length)
bytesRcvd = netStream.Read(byteReceiveBuffer, 0, BUFFER_SIZE)
receiveMessage = Encoding.ASCII.GetString(byteReceiveBuffer, 0, bytesRcvd)
netStream.Close()
client.Close()

C#:

int bytesRcvd = 0;
var byteSendBuffer = new Byte[BUFFER_SIZE - 1];
var byteReceiveBuffer = new Byte[BUFFER_SIZE - 1];
string receiveMessage = null;
byteSendBuffer = Encoding.ASCII.GetBytes(sendMessage);
System.Net.Sockets.TcpClient client = null;
System.Net.Sockets.NetworkStream netStream = null;
client = new System.Net.Sockets.TcpClient("localhost", 9060);

netStream = client.GetStream();

netStream.Write(byteSendBuffer, 0, byteSendBuffer.Length);
bytesRcvd = netStream.Read(byteReceiveBuffer, 0, BUFFER_SIZE);

receiveMessage = Encoding.ASCII.GetString(byteReceiveBuffer, 0, bytesRcvd);
netStream.Close();
client.Close();

收到的错误是:

指定的参数超出了有效值的范围。

这发生在netStream.read

嗯,是的,所以Byte 的处理方式不同.. 关注c#版本,改变:

var byteSendBuffer = new Byte[BUFFER_SIZE - 1];
var byteReceiveBuffer = new Byte[BUFFER_SIZE - 1];

到这里:

var byteSendBuffer = new Byte[BUFFER_SIZE];
var byteReceiveBuffer = new Byte[BUFFER_SIZE];

没有错误,但netStream.read 无限期挂起,所以显然没有取回任何数据,对吧?

我试着用:

if(netStream.CanRead()) { ... }

不起作用,仍然挂起。

你能找出原因吗?同样,是的,我知道这很丑陋。我会解决的。

更新

这绝对令人沮丧。我已经为此尝试了许多建议配置的示例。在新的c#(或曾经是)解决方案中,我为 TcpClient 命令添加了一个vb 项目。不管我做什么,它都会无限期地挂在read上,但可以和vb一起使用。

最终更新

嗯,所有这些麻烦和有用的建议,结果这是处理小细节的那些巨大的重大巧合之一,就像我无法访问的另一端的监听服务一样。返回要发送给侦听器的消息的过程返回了不正确的消息,并且侦听器没有响应数据,它只是超时了。如此微小的细节,(如几个字符)很难发现。

【问题讨论】:

  • New Byte[BUFFER_SIZE - 1] 相当于 C# 中的 new byte[BUFFER_SIZE]。执行GetStream().Read()时可能发生超时?
  • 正如@TetsuyaYamamoto 评论所建议的,在 VB 中创建数组时需要指定上限,而 C# 需要长度,因此在 C# 中该数字应始终大于 1。
  • @TetsuyaYamamoto - 谢谢。正确,因为我更改了BUFFER_SIZE,如问题所示。我完全不知道为什么c# 仍然无法正常工作。 vb 版本不会超时吗?必须盯着我的脸。
  • 这里没有什么明显的,但有一些常见错误的证据 - 您指的是 messages,但 TCP 不执行 messages。无法保证您对Read 的调用将收到缓冲区的副本,该缓冲区已传递给另一端对Write 的单个调用。 TCP 只是一个无穷无尽的字节流,因此任何 特定 读取调用都可能接收(例如)一个缓冲区的一部分,该缓冲区值得在另一端写入的数据,或在 多次在另一端调用Write
  • NetworkStream.Read() 阻塞(“挂起”),直到有数据可供读取。如果它永远不会继续,则意味着端点没有发送任何东西。如果您想确定在实际尝试读取之前是否有要读取的数据,请检查:if(netStream.DataAvailable) { ... }

标签: c# vb.net tcpclient


【解决方案1】:

试试这个

 bytesRcvd = netStream.Read(byteReceiveBuffer, 0,
 byteReceiveBuffer.Length);

代替

bytesRcvd = netStream.Read(byteReceiveBuffer, 0,
     BUFFER_SIZE );

你的 byteReceiveBuffer 长度是 2047,BUFFER_SIZE 是 2048

【讨论】:

  • 虽然您的回答在技术上没有错,但您的建议使 C# 代码与原始 VB 不同。更好的解决方案是首先使数组的大小正确。
  • 谢谢,但这仍然不能解决问题。它仍然挂起,无法弄清楚为什么vb.net 版本没有。如另一条评论所述,可能正盯着我的脸。
  • 感谢大家的建议,请查看我对问题的最新更新。
猜你喜欢
  • 1970-01-01
  • 2010-09-17
  • 2012-12-03
  • 2015-02-01
  • 2014-02-02
  • 2011-09-09
  • 2020-08-09
  • 1970-01-01
  • 2011-03-12
相关资源
最近更新 更多