如何重复从套接字读取数据?

3

首先,我正在使用C#编程。我通过套接字将大小不同的数据写入设备。在写入数据后,我想从套接字中读取数据,因为设备在处理完所有数据后会返回一个错误代码/完成消息。目前我的代码大致如下:

byte[] resultErrorCode = new byte[1];
resultErrorCode[0] = 255;

while (resultErrorCode[0] == 255)
{
    try
    {
        ReadFromSocket(ref resultErrorCode);
    }

    catch (Exception)
    {
    }
}
Console.WriteLine(ErrorList[resultErrorCode[0] - 48]);

我在其他地方使用ReadFromSocket,所以我知道它正常工作。结果出现的情况是,我连接的端口(在我的计算机上)会更改为随机端口。我认为这会导致另一侧固件连接不良。因此,当我在另一侧写入数据时,它会尝试将数据写入我最初连接的端口,但经过多次读取后,连接端口在我的一侧发生了更改。
如何连续从套接字中读取,直到收到完成命令?如果我知道循环出了问题,因为对于我的最小测试文件,它需要1分13秒左右的时间。我通过删除循环并使代码休眠1分15秒来测试代码。当重新启动时,它成功读取了我期望的完成命令。有人有什么建议吗?

1
这看起来像是非常基础的同步代码。你应该研究一下使用I/O完成端口的异步事件驱动套接字...或者另一个处理带有事件的C#库的套接字。 - Timmerz
@Timmerz - 我会再仔细研究一下,但我已经查看了一些关于异步套接字的内容。我不明白这如何帮助我解决这个问题。我对套接字并不是很熟悉,这基本上是我第一次尝试使用它们。 - tcannon91
同步套接字是一个可怕的想法。因此,首先应该使用基于事件的套接字。其次,通常在套接字之上实现协议,告诉诸如要读取多少字节等内容...这就像http等。我不理解随机端口的东西...我认为你只需保持连接打开直到所有通信完成即可。否则,您应该从设备接受连接,但这应该作为协议的一部分被理解,然后在这种情况下,您也必须使用侦听器。 - Timmerz
@Timmerz - 谢谢。原始编码者设置了它,我现在看到他确实在每个点使用同步写入/连接/读取。我将逐步进行修复,尽量不破坏任何东西。 - tcannon91
同步套接字是一个可怕的想法吗?在某些情况下,它们并没有什么问题,只是不能在 UI 线程上使用。关于随机端口 - 如果客户端连接到服务器,您需要指定服务器正在侦听的端口。除非您也指定了客户端端口,否则将使用“随机”端口,但通常这不应该是问题。只要连接保持打开状态,端口就不会改变。 - C.Evenhuis
@C.Evenhuis - 我认为由于我反复尝试从连接中读取数据,而且在另一个设备上仍在处理数据,所以没有读取到任何内容。代码将此解释为SocketException(因此我在循环中嵌入了try catch),为了解决这个问题,需要打开一个新的连接。这就是我认为正在发生的事情...但我不确定。每次尝试读取时,我都会打印出起始端口和IP以及结束端口和IP,并且每次读取时起始端口都会更改。 - tcannon91
1个回答

1
你应该拥有一个独立的线程,它将充当外部硬件的驱动程序。这个线程将接收所有数据,解析它并将适当的消息传输到你的应用程序的其余部分。这段代码将让你了解如何从硬件接收和解析数据的过程。
  public void ContinuousReceive(){
    byte[] buffer = new byte[1024];
    bool terminationCodeReceived = false;
    while(!terminationCodeReceived){
      try{
          if(server.Receive(buffer)>0){
             // We got something
             // Parse the received data and check if the termination code
             // is received or not
          }
      }catch (SocketException e){
          Console.WriteLine("Oops! Something bad happened:" + e.Message);
      }
    }
  }

注意事项:

  1. 如果您想在计算机上打开特定端口(某些外部硬件已配置为与预定义端口通信),则应在创建套接字时指定该端口。
  2. 除非要停止应用程序或外部硬件API要求这样做,否则不要关闭套接字。保持套接字打开将解决随机端口更改的问题。
  3. 在处理外部硬件时使用Thread.Sleep不是一个好主意。如果可能的话,您应该使用事件(在RS232连接的情况下)或阻塞调用在单独的线程上,就像上面的代码一样。

这个很好用。谢谢你。我猜原来的编码人员在他们的ReadFromSocket函数中抽象得比我想象的要多。连续调用Socket类的Receive方法似乎解决了问题。再次感谢。另外,我只是用Thread.Sleep作为一个测试,看看单次读取是否有效,而不是持续轮询,但还是谢谢你的建议 :) - tcannon91
我试着+1,但在我的声望超过15之前我做不到。 - tcannon91
当然没问题 :) 你随时可以回来 :) - GETah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接