2016-04-13 41 views
1

我在使用简单的TCP读/写应用程序时遇到了一些问题,我需要向设备/主机写入命令。通常情况下,我可以使用stream.Write()命令执行此操作,但是在使用此特定设备时,它似乎会在发送任何命令之前发回一个初始欢迎消息(PJLINK 0)。我可以使用PuTTY发送正确的命令,但在使用C#时,我认为我的连接正在关闭,然后才能通过命令。C#TCP读取欢迎消息并发送命令

所以我的问题是如何在下面调整我的代码以接收该欢迎消息,然后在没有TcpClient提前关闭连接的情况下发回命令(我不需要读取响应)?

任何帮助将不胜感激。

   using (tcpClientA = new TcpClient()) 
       { 
        int portA = 4352; 

        if (!tcpClientA.BeginConnect("10.0.2.201", portA, null, null).AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1.0))) 
        { 
         throw new Exception("Failed to connect."); 
        } 

        while (tcpClientA.Connected) 
        { 
         using (streamA = tcpClientA.GetStream()) 
         { 
          if (type == "raw") 
          { 

           // Buffer to store the response bytes. 
           byte[] writeBufferC = Encoding.ASCII.GetBytes("%1 INPT 32$0D"); //Command I need to send 
           byte[] readBufferC = new byte[tcpClientA.ReceiveBufferSize]; 
           string fullServerReply = null; 
           using (var writer = new MemoryStream()) 
           { 
            do 
            { 
             int numberOfBytesRead = streamA.Read(readBufferC, 0, readBufferC.Length); 
             if (numberOfBytesRead <= 0) 
             { 
              break; 
             } 
             writer.Write(writeBufferC, 0, writeBufferC.Length); 
            } while (streamA.DataAvailable); 
            fullServerReply = Encoding.UTF8.GetString(writer.ToArray()); 
            Console.WriteLine(fullServerReply.Trim()); 
           } 
          } 
         } 
        } 
       } 

更新1 删除了BeginConnect和异步方法。

   using (tcpClientA = new TcpClient()) 
       { 
        int portA = 4352; 

        tcpClientA.Connect("10.0.2.201", portA); 

        while (tcpClientA.Connected) 
        { 
         using (streamA = tcpClientA.GetStream()) 
         { 
          if (type == "raw") 
          { 
           byte[] readBufferC = new byte[tcpClientA.ReceiveBufferSize]; 
           byte[] writeBufferC = Encoding.ASCII.GetBytes("%1 INPT 31$0D"); //Command I need to send 

           string fullServerReply = null; 
           using (var writer = new MemoryStream()) 
           { 
            do 
            { 
             streamA.Read(readBufferC, 0, readBufferC.Length); //First read 
             writer.Write(writeBufferC, 0, writeBufferC.Length); //Send command 
            } while (streamA.DataAvailable); 
            fullServerReply = Encoding.UTF8.GetString(readBufferC.ToArray()); 
            Console.WriteLine(fullServerReply.Trim()); 
            tcpClientA.Close(); 
           } 
          } 
         } 
        } 
       } 
+0

什么*精确*你的意思是“消息”?如果你不知道,你将没有机会得到这个权利。要发送和接收消息,您必须知道*正确*消息*是*,否则无法正确编写代码。 TCP不是一种消息协议,它是一种字节流协议。要发送消息,你需要一个消息协议 - 我们不知道你使用的是什么消息协议,因为你没有告诉我们。 –

+0

它是在一些异步方法吗?我怀疑'BeginConnect'是个问题。跳过'AsyncWaitHandle'部分,并同步连接。使用'.Connect' – ntohl

+0

您也可以在每个命令之后阅读。它以这种方式工作吗?按照规范,它看起来像你需要在开始时阅读一次。读取每个缓冲区后,还可以将%1 ...字符串写入内存流。 – ntohl

回答

0

DataAvailable不会告诉你远程端将来会发送多少数据。它的用途几乎总是一个错误。在这里,它会导致您提前随机退出循环。

阅读,直到你有你期望的所有字节或直到流被关闭。

这是一个基于行的协议吗?实例化一个StreamReader并从流中绘制整行。

while (tcpClientA.Connected)完成任何事情。即使它返回true,连接也会在1纳秒后丢失。无论如何,你的代码必须处理。它应该是while (true)。这不是一个错误,它只是显示了对TCP的理解薄弱,所以我指出了这一点。

删除所有用法ReceiveBufferSize。这个值意味着没有意义。相反,请使用固定的缓冲区大小。我发现4096在吞吐量不是很高的情况下效果很好。

numberOfBytesRead <= 0应该是==0。同样,不是一个错误,但你似乎并不完全理解API的功能。这很危险。

在更新的代码中,您没有使用返回值streamA.Read这是一个错误。您试图通过修剪生成的\0字符来修复该错误。这只是治疗症状,并不是一个真正的解决办法。

你需要一个套接字教程。这场大屠杀的出现是因为你不依赖最佳实践。如果做得对,套接字读取循环实际上相当简单。此代码是可能出错的集合。