C#TCPClient / Socket编写没有抛出异常

时间:2014-07-02 18:24:38

标签: c# sockets tcp tcpclient

我尝试通过tcp连接连接许多打印机。我试图验证我的TcpClient仍然连接更新GUI。我正在尝试写入套接字以确保它仍然连接。即使拔掉电缆我也没有例外我在这里尝试了所有建议MSDN_Fourm

我尝试检查打印机状态后收到预期的异常

psudo代码 client是先前已连接的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返回:true

电缆未插电

FuntionPsudo返回:true

FuntionPsudo返回:true

检查打印机状态

FuntionPsudo返回:false

预先感谢您提供有关可能发生这种情况和/或如何解决问题的任何帮助

4 个答案:

答案 0 :(得分: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中的一些代码,所以也应该给他们一些信用;)

答案 1 :(得分:0)

您只能通过发送内容和接收内容来判断您是否仍然处于连接状态。即使将字节输入黑洞,只需将字节输入网络即可。 Connected属性不可靠,几乎所有使用它的代码都是错误的。

向打印机发送内容并收到回复。或者,创建一个新连接(内部将发送和接收没有数据的TCP控制数据包)。

答案 2 :(得分:-1)

在处理TCP协议等传输层时,您需要像对待Walkie-Talkie一样使用它。你需要决定谈话的时间和时间。换句话说,当双方同时说话或倾听时,通信就会崩溃。

以下是Nutshell中的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();
    }
}

答案 3 :(得分:-1)

我有同样的问题可以重新连接。 我用Java编写服务器,用C#编写客户端(统一) java-Java抛出异常好 java-c#:在某些情况下,它们都抛出异常。

我拥有性能服务器的最佳方法 我通过以下方式解决:编写jar客户端并使用ikvm导出到dll(将jar复制到ikvm / bin)。在C#中创建库并引用dll + ikvm.core.dll + ... / manage / unityEngine.dll ==>将Cshapr / bin / Debug复制到UnityProJect / Asset ->运行正常,但构建速度超过了37M

如果您希望拥有小型客户端->无需重新连接的网络