TCPClient/Socket写入不抛出异常

本文关键字:抛出异常 Socket TCPClient | 更新日期: 2023-09-27 18:11:14

我试图通过tcp连接连接到许多打印机。我正试图验证我的TcpClient是否仍然连接以更新GUI。我正试图写一个套接字,以确保它仍然连接。我没有得到任何例外,即使电缆被拔掉,我尝试了这里所有的建议MSDN_Fourm

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

psudo-codeclient是一个先前已经连接的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;
}

函数psudo返回:true

电缆不插电

函数psudo返回:true

函数psudo返回:true

检查打印机状态

函数psudo返回:false

提前感谢任何帮助,为什么这可能会发生和/或如何修复它

TCPClient/Socket写入不抛出异常

经过几次失败的尝试后,我意识到"拔掉电缆"类型的连接检测并不那么容易。同时,我发现有几个技巧可以检查服务器是否已关闭连接,所有这些都不需要发送心跳类型的消息。

这是我想到的,我可以说它在大多数时候都是有效的(特别是在电缆断开的情况下,很难确定连接是否仍然畅通)

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关于检查客户端断开连接的回答和Greg Dean关于在套接字上设置keep-alive的回答中的一些代码,所以一些荣誉也应该归于他们;

你只能通过发送和接收来判断你是否还在连接。仅仅将字节推入网络总是有效的,即使它们进入黑洞。Connected属性是不可靠的,几乎所有使用它的代码都是错误的。

发送一些东西到打印机并收到回复。或者,创建一个新的连接(它将在内部发送和接收TCP控制数据包,而不包含数据)。

当处理像TCP协议这样的传输层时,你需要像使用对讲机一样使用它。你需要决定谈话的时间和时间。换句话说,当双方同时说话或倾听时,沟通就会中断。

下面是c# in a Nutshell一书中的一个例子:

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();
    }
}

我在重新连接时有同样的问题。我用java写服务器,用c# (unity)写客户端。java抛出异常java-c#:两者在某些情况下都会抛出异常。

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

如果你想有一个小的客户端->网络没有重新连接