2016-04-13 39 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字符來修復該錯誤。這只是治療症狀,並不是一個真正的解決辦法。

你需要一個套接字教程。這場大屠殺的出現是因爲你不依賴最佳實踐。如果做得對,套接字讀取循環實際上相當簡單。此代碼是可能出錯的集合。