心跳包和通讯的问题
以下是服务器端的,使用异步回调,关于Socket连接、接收数据和发送数据的一个简单demo,代码如下:
对于这个demo,有一个问题就是Socket连接会越连越多,因为没有心跳机制,当客户端意外断开服务器收不到断开请求时,Socket会一直连接并不会断开,浪费了资源。
1、请帮忙加上心跳机制,或者给出其他更好的方案
2、请贴出详细代码
谢谢。
class test
{
public static ManualResetEvent ClientConn = new ManualResetEvent(false);
public static int Online = 0;
static void Main(string[] args)
{
IPAddress IP = Dns.GetHostAddresses(Dns.GetHostName())[0];
int Port = 21062;
TcpListener listener = new TcpListener(IP, Port);
Console.WriteLine("the server ip is {0},and port is {1}", IP, Port);
try
{
listener.Start();
while (true)
{
ClientConn.Reset();
listener.BeginAcceptSocket(AsyncAcceptSocketCallback, listener);
ClientConn.WaitOne();
}
}
catch (Exception)
{
Console.WriteLine("服务启动失败");
ClientConn.Set();
}
}
static void AsyncAcceptSocketCallback(IAsyncResult ar)
{
StateObject StateObject = new StateObject();
try
{
ClientConn.Set();
TcpListener listener = (TcpListener)ar.AsyncState;
Socket Socket = listener.EndAcceptSocket(ar);
IPEndPoint ip = (IPEndPoint)Socket.RemoteEndPoint;
string UserIP = ip.Address.ToString().TrimEnd() + ":" + ip.Port.ToString().TrimEnd();
StateObject.Socket = Socket;
StateObject.UserIP = UserIP;
Online = Online + 1;
Console.WriteLine("[连]来自{0}在{1}连接,当前在线人数:{2}", StateObject.UserIP, DateTime.Now.ToString("HH:mm:ms"), Online);
StateObject.Socket.BeginReceive(
StateObject.Buffer, 0, StateObject.BufferSize, SocketFlags.None, AsyncReceiveCallback, StateObject);
}
catch
{
Exception(StateObject);
}
}
static void AsyncReceiveCallback(IAsyncResult ar)
{
StateObject StateObject = ar.AsyncState as StateObject;
try
{
StateObject.ReceiveSize = StateObject.Socket.EndReceive(ar);
Console.WriteLine("[收]收到来自{0}发送的数据,时间{1},正在验证中...", StateObject.UserIP, DateTime.Now.ToString("HH:mm:ms"));
if (StateObject.ReceiveSize > 0)
{
ThreadPool.QueueUserWorkItem(UnPackAndSendBuffer, StateObject);
StateObject.Socket.BeginReceive(StateObject.Buffer, 0, StateObject.BufferSize, SocketFlags.None, AsyncReceiveCallback, StateObject);
}
else
{
Exception(StateObject);
}
}
catch //(SocketException se)
{
Exception(StateObject);
}
}
static void UnPackAndSendBuffer(object o)
{
Thread.CurrentThread.Priority = ThreadPriority.Highest;
byte[] Result = new byte[] { };
StateObject StateObject = o as StateObject;
UnPack UnPack = new UnPack();
try
{
//这里是解析数据包,并组合一个byte[],发送Result给客户端
Result = UnPack.UnPackAndGetData(StateObject.Buffer, StateObject.ReceiveSize, StateObject.UserIP);
if (Result.Length > 0)
{
StateObject.Socket.BeginSend(Result, 0, Result.Length, SocketFlags.None, AsyncSendCallback, StateObject);
Console.WriteLine("[发]已发送数据到{0},时间{1}\n", StateObject.UserIP, DateTime.Now.ToString("HH:mm:ms"));
}
else
{
Console.WriteLine("[错]解包失败01,来自{0},时间{1}\n", StateObject.UserIP, DateTime.Now.ToString("HH:mm:ms"));
Exception(StateObject);
}
}
catch //(Exception e)
{
Console.WriteLine("[错]解包失败,来自{0},时间{1}", StateObject.UserIP, DateTime.Now.ToString("HH:mm:ms"));
Exception(StateObject);
}
}
static void AsyncSendCallback(IAsyncResult ar)
{
StateObject StateObject = ar.AsyncState as StateObject;
try
{
StateObject.Socket.EndSend(ar);
}
catch //(SocketException se)
{
Exception(StateObject);
}
}
public class StateObject
{
public Socket Socket = null;
public const int BufferSize = 128;
public byte[] Buffer = new byte[BufferSize];
public int ReceiveSize = 0;
public string UserIP = string.Empty;
}
static void Exception(StateObject o)
{
if (o.Socket != null)
{
o.Socket.Close();
o.Socket = null;
Online = Online - 1;
}
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("[断]来自{0}已断开,时间{1},当前在线人数:{2}\n", o.UserIP, DateTime.Now.ToString("HH:mm:ms"), Online);
Console.ForegroundColor = ConsoleColor.Green;
}
}
对于这个demo,有一个问题就是Socket连接会越连越多,因为没有心跳机制,当客户端意外断开服务器收不到断开请求时,Socket会一直连接并不会断开,浪费了资源。
1、请帮忙加上心跳机制,或者给出其他更好的方案
2、请贴出详细代码
谢谢。
...全文
相关推荐
Java心跳包功能TCP实现
- 在日志系统中记录心跳包的发送和接收情况,便于问题排查。通过以上步骤,你可以构建出一个基本的Java心跳包功能的TCP实现。
C#WPF与PLC心跳通讯,时间同步等
心跳机制是为了确保通讯的可靠性和实时性,它定期发送验证请求,如果PLC未响应,则可能表示通讯链路出现问题。2. **心跳通讯**:心跳机制是一种常见的网络通信策略,用于检测通讯连接是否仍然有效。
Python搭建即时通讯系统
在即时通讯系统中,客户端和服务器会周期性地发送心跳包,若在一定时间内未收到对方的心跳包,就可以判断连接已断开,并采取重新连接的措施。
Java Socket编程心跳包创建实例解析
采用定时发送简单的通讯包,如果在指定时间段内未收到对方响应,则判断对方已经离线。二、心跳包的作用心跳包的主要作用是检测TCP的异常断开。
Android的socket长连接(心跳检测)
在Android开发中,Socket长连接是一种常见的通信方式,特别是在实时性要求高的应用中,如即时通讯、在线游戏等。为了保持连接的稳定性和检测网络状况,通常会采用心跳检测机制。


