72 .net c# sockets connection tcp
如何检测客户端是否与服务器断开连接?
我有下面的代码在我的AcceptCallBack
方法
static Socket handler = null;
public static void AcceptCallback(IAsyncResult ar)
{
//Accept incoming connection
Socket listener = (Socket)ar.AsyncState;
handler = listener.EndAccept(ar);
}
Run Code Online (Sandbox Code Playgroud)
我需要找到一种方法来尽快发现客户端已从handler
Socket 断开连接.
我试过了:
handler.Available;
handler.Send(new byte[1], 0,
SocketFlags.None);
handler.Receive(new byte[1], 0,
SocketFlags.None);
当您连接到服务器并且想要检测服务器何时断开连接但是当您是服务器并且想要检测客户端断开连接时它们不起作用时,上述方法会起作用.
任何帮助将不胜感激.
Sam*_*uel 101
由于在断开套接字时没有可用于发出信号的事件,因此您必须以您可接受的频率轮询它.
使用此扩展方法,您可以使用可靠的方法来检测套接字是否已断开连接.
static class SocketExtensions
{
public static bool IsConnected(this Socket socket)
{
try
{
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException) { return false; }
}
}
Run Code Online (Sandbox Code Playgroud)
Maj*_*jak 14
有人提到TCP套接字的keepAlive功能.这里描述得很好:
http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
我正在使用它:在连接套接字后,我正在调用此函数,它将keepAlive设置为on.该keepAliveTime
参数指定超时(以毫秒为单位),在发送第一个保持活动数据包之前没有活动.该keepAliveInterval
参数指定在未收到确认的情况下发送连续保持活动数据包之间的间隔(以毫秒为单位).
void SetKeepAlive(bool on, uint keepAliveTime , uint keepAliveInterval )
{
int size = Marshal.SizeOf(new uint());
var inOptionValues = new byte[size * 3];
BitConverter.GetBytes((uint)(on ? 1 : 0)).CopyTo(inOptionValues, 0);
BitConverter.GetBytes((uint)time).CopyTo(inOptionValues, size);
BitConverter.GetBytes((uint)interval).CopyTo(inOptionValues, size * 2);
socket.IOControl(IOControlCode.KeepAliveValues, inOptionValues, null);
}
Run Code Online (Sandbox Code Playgroud)
我也在使用同步阅读:
socket.BeginReceive(packet.dataBuffer, 0, 128,
SocketFlags.None, new AsyncCallback(OnDataReceived), packet);
Run Code Online (Sandbox Code Playgroud)
在回调中,这里被捕获超时SocketException
,当套接字在保持活动数据包之后没有得到ACK信号时会引发超时.
public void OnDataReceived(IAsyncResult asyn)
{
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = socket.EndReceive(asyn);
catch (SocketException ex)
{
SocketExceptionCaught(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
这样,我就能安全地检测TCP客户端和服务器之间的断开连接.
Eri*_*sch 13
这根本不可能.您和服务器之间没有物理连接(极少数情况下,您使用环回电缆连接两个编译器).
正常关闭连接后,将通知另一方.但是如果连接以其他方式断开(比如用户连接被丢弃),那么服务器将不会知道,直到它超时(或尝试写入连接并且确认超时).这就是TCP工作的方式,你必须忍受它.
因此,"即时"是不现实的.您可以做的最好的事情是在超时期限内,这取决于代码运行的平台.
编辑:如果您只是寻找优美的连接,那么为什么不从您的客户端向服务器发送"DISCONNECT"命令呢?
小智 6
"这就是TCP的工作方式,你必须忍受它."
是的,你是对的.这是生活中我已经意识到的事实.即使在使用该协议(甚至其他协议)的专业应用程序中,您也会看到相同的行为.我甚至看到它出现在网络游戏中; 你哥们说"再见",他似乎又在网上待了1-2分钟,直到服务员"清理房子".
您可以在此处使用建议的方法,或实施"心跳",如同建议的那样.我选择前者.但是,如果我确实选择了后者,我只需让服务器每隔一个字节"ping"一个客户端,看看我们是否有超时或没有响应.您甚至可以使用后台线程来实现精确计时.如果你真的担心它,甚至可以在某种选项列表(枚举标志或其他东西)中实现组合.但是,只要你更新,在更新服务器方面有一点延迟并不是什么大不了的事.这是互联网,没有人期望它是魔术!:)