指定的参数超出了有效值的范围.参数名称:大小和串口通信

dav*_*nog 1 c# sockets serial-port windows-ce

我需要创建一个应用程序,它需要使用TCP/IP与现有软件进行通信,其中我和其他应用程序将使用下面指定的端口号.

private void frmScan_Load(object sender, EventArgs e)
{
    clientSocket.Connect("100.100.100.30", 76545);
}

public void msg(string mesg)
{
    textBox1.Text = textBox1.Text + Environment.NewLine + " >> " + mesg;
}

private void cmdSCANok_Click(object sender, EventArgs e)
{

    msg("Client Started");
    NetworkStream serverStream = clientSocket.GetStream();
    byte[] outStream = Encoding.ASCII.GetBytes("PCK|SCAN|5025066840471");

    serverStream.Write(outStream, 0, outStream.Length);
    serverStream.Flush();

    byte[] inStream = new byte[10025];
    serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
    string returndata = Encoding.ASCII.GetString(inStream, 0, inStream.Length);


    msg("Data from Server : " + returndata);
} 
Run Code Online (Sandbox Code Playgroud)

发生的事情是,我正在与之通信的程序有一些内置语言,它将理解我发送的代码,它将根据我发送的代码返回数据.所以在上面的代码中,我发送了三位代码:( "PCK|SCAN|5025066840471"),它将在数据库中找到一个特定的项目.当它运行时,我在行上出错:

serverStream.Read(inStream, 0, (int)clientSocket.ReceiveBufferSize);
Run Code Online (Sandbox Code Playgroud)

错误显示以下内容:"指定的参数超出有效值范围.参数名称:大小"

我按照我在本网站上看到的教程:http://csharp.net-informations.com/communications/csharp-client-socket.htm - 但我做的略有不同.所以不要放

string returndata = Encoding.ASCII.GetString(inStream);
Run Code Online (Sandbox Code Playgroud)

我写:

string returndata = Encoding.ASCII.GetString(inStream, 0, inStream.Length); 
Run Code Online (Sandbox Code Playgroud)

我对于为什么会遇到这些问题感到非常困惑,说实话,我对代码的作用并不了解,我只是有一个粗略的想法,但还不足以解决这个问题.有人可以帮忙吗?

非常感激!

PS:我在Visual Studio 2010上为Windows CE(便携式设备)编程.

Lua*_*aan 13

您的代码是如何不进行TCP通信的一个很好的例子.我已经多次看到这段代码被复制了,我很高兴为您指出一个关于TCP的好教程 - 太糟糕了我还没见过一个:)

我先指出一些错误:

  • TCP不保证数据包以一串字节的形式到达.因此(理论上)Write操作可能导致分裂,另一方面需要两次读取.通过TCP发送没有标题的数据是一个非常糟糕的主意 - 接收方不知道它需要读多少.所以你有两个选择 - 在数据本身之前写入整组数据的长度,或者使用控制字符来结束"数据包"
  • 第一点也应该澄清你的阅读也是错误的.读取整个"命令"可能需要多次读取操作,或者单次读取操作可能会同时为您提供两个命令!
  • 您正在将ReceiveBufferSize字节读入10025长缓冲区.ReceiveBufferSize可能比你的缓冲区大.要这样做 - 读取最大数量inStream.Length.如果您使用C++进行编码,这将是缓冲区溢出的一个很好的例子.
  • 当您将数据转换为字符串时,您希望整个缓冲区已满.这很可能不是这种情况.相反,您必须存储读取调用的返回值 - 它告诉您实际读取了多少字节.否则,你正在读垃圾,基本上有另一个缓冲区溢出.

所以更好(但仍然远非完美)的实现将是这样的:

NetworkStream serverStream = clientSocket.GetStream();
byte[] outStream = Encoding.ASCII.GetBytes("PCK|SCAN|5025066840471");

// It would be much nicer to send a terminator or data length first, 
// but if your server doesn't expect that, you're out of luck.
serverStream.Write(outStream, 0, outStream.Length);

// When using magic numbers, at least use nice ones :)
byte[] inStream = new byte[4096];

// This will read at most inStream.Length bytes - it can be less, and it
// doesn't tell us how much data there is left for reading.
int bytesRead = serverStream.Read(inStream, 0, inStream.Length);

// Only convert bytesRead bytes - the rest is garbage
string returndata = Encoding.ASCII.GetString(inStream, 0, bytesRead);
Run Code Online (Sandbox Code Playgroud)

哦,我必须推荐这篇关于TCP协议设计的文章.

它讨论了许多关于TCP的误解,最重要的是看消息框架部分.