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
提前感谢任何帮助,为什么这可能会发生和/或如何修复它
经过几次失败的尝试后,我意识到"拔掉电缆"类型的连接检测并不那么容易。同时,我发现有几个技巧可以检查服务器是否已关闭连接,所有这些都不需要发送心跳类型的消息。
这是我想到的,我可以说它在大多数时候都是有效的(特别是在电缆断开的情况下,很难确定连接是否仍然畅通)
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
如果你想有一个小的客户端->网络没有重新连接