2014-07-02 98 views
3

我有很多打印機,我試圖通過TCP連接來連接。我試圖驗證我的TcpClient仍然連接到更新GUI。我試圖寫入一個套接字,以確保它仍然連接。我沒有得到任何例外,即使拔掉電源線我嘗試了所有的建議,這裏MSDN_FourmC#TCPClient /套接字寫入不拋出異常

我收到預期的異常後,我嘗試檢查打印機狀態

psudo碼 客戶端具有的TcpClient先前已經連接

private bool FuntionPsudo(){ 
    try{ 
     if(client.Connected){ 
      byte[] buf = new byte[1]; 
      client.Client.Send(buf, 0,0); 
      client.GetStream().Write(buf,0,0); 
      if(client.Client.Receive(buf,SocketFlags.Peek)==0) 
       return false; 
      return true; 
     } 
    } 
    catch(Exception){ 
     return false; 
    } 

    return false; 
} 

FuntionPsudo返回:

電纜拔出

FuntionPsudo返回:

FuntionPsudo返回:

檢查打印機狀態

FuntionPsudo回報:假

在此先感謝您的幫助,爲什麼這可能發生的和/或如何修復它

+0

拔下電纜不會自動關閉現有連接,因爲該連接的任何一側都不關心/瞭解物理狀態。這就是超時的目的。 – admdrew

+0

好的,但是當我寫入套接字時,它不應該拋出異常? – user2144406

+0

除非連接/插座實際上已關閉。如果您手動關閉套接字,或者等待很長時間以使連接超時,您是否會遇到異常? – admdrew

回答

0

經過多次失敗的嘗試,我意識到'拔掉電纜'連接檢測類型並不容易。同時,我發現有幾個技巧可以檢查服務器是否關閉了連接,所有這些都不需要發送聽到類型的消息。

這裏是我想出了,我可以說,它工作的時間(尤其是電纜斷開,這並不容易弄清楚,如果連接仍高達)

static class SocketUtils 
{ 
    public static bool IsConnected(this Socket socket) 
    { 
     return IsSocketConnected(socket) && IsNetworkConnected(socket); 
    } 

    public static void KeepAlive(this Socket socket, int pollSeconds) 
    { 
     socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); 
     SetIOControlKeepAlive(socket, (uint)(pollSeconds * 1000), 1); 
    } 

    static bool IsNetworkConnected(this Socket socket) 
    { 
     try 
     { 
      return socket.Send(new byte[0]) == 0; 
     } 
     catch (SocketException) { return false; } 
    } 

    static bool IsSocketConnected(this Socket socket) 
    { 
     try 
     { 
      return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0); 
     } 
     catch (SocketException) { return false; } 
    } 

    static void SetIOControlKeepAlive(Socket socket, uint time, uint interval) 
    { 
     var sizeOfUint = Marshal.SizeOf(time); 
     var inOptionValues = new byte[sizeOfUint * 3]; 
     BitConverter.GetBytes((uint)(time == 0 ? 0UL : 1UL)).CopyTo(inOptionValues, 0); 
     BitConverter.GetBytes(time).CopyTo(inOptionValues, sizeOfUint); 
     BitConverter.GetBytes(interval).CopyTo(inOptionValues, sizeOfUint * 2); 

     socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null); 
    } 
} 

這裏是你如何能最使用方法:

var tcpClient = new TcpClient(); 

tcpClient.Connect("192.168.2.20", 3000); 

// set this to a low value to detect cable disconnects early 
tcpClient.Client.KeepAlive(30); // 30 seconds 

Console.WriteLine("Connected.."); 
while (true) 
{ 
    Thread.Sleep(500); 
    Console.WriteLine(tcpClient.Client.IsConnected()); 
} 

我必須補充一點,我無恥地複製從Samuel's answer about checking client disconnectsGreg Dean's answer about setting keep-alive on the socket一些代碼,所以一些信貸應該去他們爲好;)

+0

這不起作用更好,同樣的問題 – user2144406

+0

我試過了,它仍然不起作用 – user2144406

+0

@ user2144406結合上面的代碼?或嘗試過嗎? – ziya

-1

當處理像TCP協議這樣的傳輸層時,您需要像使用「對講機」一樣使用它。你需要決定什麼時候和多長時間說話。換句話說,當雙方同時談話或聆聽時,溝通就會崩潰。

這是從書C#果殼中的一個例子:

using System; 
using System.IO; 
using System.Net; 
using System.Net.Sockets; 
using System.Threading; 

class TcpDemo 
{ 
    static void Main() 
    { 
     new Thread(Server).Start();  // Run server method concurrently. 
     Thread.Sleep(500);    // Give server time to start. 
     Client();   
    } 

    static void Client() 
    { 
     using (TcpClient client = new TcpClient("localhost", 51111)) 
     using(NetworkStream n = client.GetStream()) 
     { 
      BinaryWriter w = new BinaryWriter(n); 
      w.Write("Hello"); 
      w.Flush(); 
      Console.WriteLine(new BinaryReader(n).ReadString()); 
     } 
    } 

    static void Server() 
    { 
     TcpListener listener = new TcpListener(IPAddress.Any, 51111); 
     listener.Start(); 
     using(TcpClient c = listener.AcceptTcpClient()) 
     using(NetworkStream n = c.GetStream()) 
     { 
      string msg = new BinaryReader(n).ReadString(); 
      BinaryWriter w = new BinaryWriter(n); 
      w.Write(msg + " right back!"); 
      w.Flush(); 
     } 
     listener.Stop(); 
    } 
} 
+1

好吧我得到你的前提,但是看不到這真的適用,也許你可以稍微解釋一下 – user2144406

+0

你必須遵循這個順序。 1.打開TcpClient; 2.寫; 3.關閉; 4.打開TcpLister; 5.閱讀; 6.關閉。如果你打開TcpClient然後你寫,那麼你聽不起來。在示例代碼中,「使用」關注關閉,因此您不會看到關閉。 – Pabinator

0

你只能告訴你是否通過發送一些東西,接受東西回來還是連接與否。只要將字節推入網絡,即使進入黑洞也能正常工作。 Connected屬性是不可靠的,幾乎所有使用它的代碼都是錯誤的。

發送一些東西給打印機並收到回覆。或者,創建一個新的連接(內部將發送和接收沒有數據的TCP控制包)。

+0

創建一個新的連接確實有效,但是這需要很長時間,所以只是爲了澄清在沒有建立新連接的情況下它是否仍然連接?那是你在說什麼?寫入和響應代碼不是發送和接收回來的東西嗎? – user2144406

+0

是的,連接的屬性是不可靠的(謝謝你!),但發送一個空的消息實​​際上應該通過電線發送一個TCP數據包(這實質上是保持活動狀態)和_should_更新套接字狀態。 – ziya

+0

這就是我的想法...... – user2144406