当前位置: 首页 > wzjs >正文

自己电脑上做的网站 怎么让别人看千峰培训出来好就业吗

自己电脑上做的网站 怎么让别人看,千峰培训出来好就业吗,企业进行网站建设的方式有哪些,编写网页的软件叫什么文章目录 1 Disconnect 方法2 心跳消息 ​ 在客户端主动退出时,我们会调用 socket 的 ShutDown() 和 Close() 方法,但调用这两个方法后,服务器端无法得知客户端已经主动断开。 ​ 本文主要介绍在网络通信中,如何服务端如何判断客…

文章目录

  • 1 Disconnect 方法
  • 2 心跳消息

​ 在客户端主动退出时,我们会调用 socket 的 ShutDown()Close() 方法,但调用这两个方法后,服务器端无法得知客户端已经主动断开。

​ 本文主要介绍在网络通信中,如何服务端如何判断客户端断开连接。

1 Disconnect 方法

​ Socket 当中有一个专门在客户端使用的方法:Disconnect 方法。

  • 此方法将结束连接并将 Connected 属性设置为 false。但是,如果 reuseSockettrue,则可以重用套接字。
  • 若要确保在关闭套接字之前发送和接收所有数据,应在调用 Disconnect 方法之前调用 Shutdown。

客户端

​ 在程序退出时,主动断开连接。

public class NetManager : MonoBehaviour
{...public void OnDestroy(){if (_socket != null){Debug.Log("客户端主动断开连接...");_isConnected = false;_socket.Shutdown(SocketShutdown.Both);_socket.Disconnect(false);_socket.Close();_socket = null;}}...
}

服务端

  1. 收发消息时判断 socket 是否已经断开。

    namespace NetLearningTcpServerExercise2;using System.Net.Sockets;public class ClientSocket
    {private static int _ClientBeginId = 1;private Socket _socket;private byte[] _cacheBytes = new byte[1024 * 1024]; // 缓冲区,大小为 1MBprivate int    _cacheBytesLength;public int Id;public bool Connected{get => _socket == null ? false : _socket.Connected;}...public void ReceiveMessage(){if (!Connected) // 判断是否连接{Program.ServerSocket.AddDelSocket(this);return;}try{if (_socket.Available > 0){var buffer        = new byte[1024 * 5];var receiveLength = _socket.Receive(buffer);HandleReceiveMessage(buffer, receiveLength);}}catch (Exception e){Console.WriteLine("ReceiveMessage Wrong: " + e);Program.ServerSocket.AddDelSocket(this); // 解析错误,也认为把消息断开}}...
    }
    
  2. 处理删除记录的 socket 的相关逻辑(使用线程锁)。

namespace NetLearningTcpServerExercise2;using System.Net;
using System.Net.Sockets;public class ServerSocket
{private readonly Socket _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);private Dictionary<int, ClientSocket> _clientSockets = new Dictionary<int, ClientSocket>();private List<ClientSocket> _delList = new List<ClientSocket>(); // 待移除列表private bool _Running;...private void ReceiveMessage(object? state){while (_Running){lock (_clientSockets){if (_clientSockets.Count > 0){foreach (var clientSocket in _clientSockets.Values){clientSocket.ReceiveMessage();}ClearDelSocket(); // 每次循环,检查是否有待移除的 socket}}}}private void ClearDelSocket(){// 移除for (int i = 0; i < _delList.Count; i++){CloseClientSocket(_delList[i]);}_delList.Clear();}public void CloseClientSocket(ClientSocket socket){lock (_clientSockets){Console.WriteLine("ClientSocket Close: " + socket.Id);_clientSockets.Remove(socket.Id);socket.Close();}}public void AddDelSocket(ClientSocket socket){if (!_delList.Contains(socket)){_delList.Add(socket);// Console.WriteLine(socket);}}
}

测试

​ 启动服务器后,运行 Unity 并立刻结束运行,服务器中可以看到如下消息:

image-20250504092837596

2 心跳消息

​ 很多情况下,客户端并不会像上述一样正常断开连接。例如

  1. 非正常关闭客户端时,服务器无法正常收到关闭连接消息。
  2. 客户端长期不发送消息,防火墙或者路由器会断开连接。

​ 因此,在长连接中,客户端和服务端之间会定期发送的一种特殊数据包,用于通知对方自己还在线,以确保长连接的有效性。

​ 由于其发送的时间间隔往往是固定的持续的,就像是心跳一样一直存在,所以我们称之为**“心跳消息”**。

客户端

  1. 定义心跳消息

     public class HeartMessage : INetMessage
    {public int MessageId { get => 999; }public int BytesLength { get => sizeof(int) + sizeof(int); }public byte[] ToBytes(){var length = BytesLength;var bytes  = new byte[length];var index  = 0;index = this.Write(bytes, index, MessageId);// 写入消息长度index = this.Write(bytes, index, length - sizeof(int) * 2); // 减去消息长度和消息 Id 的长度return bytes;}public int FromBytes(byte[] bytes, int index){return index;}
    }
    
  2. 定时发送消息。

    public class NetManager : MonoBehaviour
    {public static NetManager Instance { get; private set; }private Socket _socket;/// <summary>/// 发送消息的公共队列,主线程塞消息,发送线程拿消息进行发送/// </summary>private Queue<INetMessage> _sendMessages = new Queue<INetMessage>();/// <summary>/// 接收消息的公共队列,主线程拿消息,接收线程获取消息塞进去/// </summary>private Queue<INetMessage> _receiveMessages = new Queue<INetMessage>();private bool _isConnected{get => _socket == null ? false : _socket.Connected;}private byte[] _cacheBytes = new byte[1024 * 1024]; // 缓冲区,大小为 1MBprivate int    _cacheBytesLength;private static readonly int _SEND_HEART_MSG_TIME = 2;private void Awake(){Instance = this;// 循环定时给服务端发送心跳消息InvokeRepeating(nameof(SendHeartMsg), 0, _SEND_HEART_MSG_TIME);}public void SendHeartMsg(){if (_isConnected){Send(new HeartMessage());}Debug.Log("发送心跳消息: " + _isConnected);}...
    }
    

服务器

​ 不停检测上次收到某客户端消息的时间,如果超时则认为连接已经断开

namespace NetLearningTcpServerExercise2;using System.Net.Sockets;public class ClientSocket
{private static int _ClientBeginId = 1;private Socket _socket;private byte[] _cacheBytes = new byte[1024 * 1024]; // 缓冲区,大小为 1MBprivate int    _cacheBytesLength;public int Id;private        long _frontTime     = -1; // 上次收到的心跳时间private static int  _TIME_OUT_TIME = 5;public bool Connected{get => _socket == null ? false : _socket.Connected;}public ClientSocket(Socket socket){Id      = _ClientBeginId++;_socket = socket;ThreadPool.QueueUserWorkItem(CheckTimeOut, null);}/// <summary>/// 间隔一段时间检测超时/// </summary>/// <param name="state"></param>private void CheckTimeOut(object? state){while (Connected){if (_frontTime != -1 &&DateTime.Now.Ticks / TimeSpan.TicksPerSecond - _frontTime > _TIME_OUT_TIME){Program.ServerSocket.AddDelSocket(this);break;}Thread.Sleep(1000);}}public void Close(){if (_socket != null){_socket.Shutdown(SocketShutdown.Both);_socket.Close();_socket = null!;}}public void SendMessage(INetMessage message){if (!Connected){Program.ServerSocket.AddDelSocket(this);return;}try{_socket.Send(message.ToBytes());}catch (Exception e){Console.WriteLine("SendMessage Wrong: " + e);Program.ServerSocket.AddDelSocket(this);}}public void ReceiveMessage(){if (!Connected){Program.ServerSocket.AddDelSocket(this);return;}try{if (_socket.Available > 0){var buffer        = new byte[1024 * 5];var receiveLength = _socket.Receive(buffer);HandleReceiveMessage(buffer, receiveLength);}}catch (Exception e){Console.WriteLine("ReceiveMessage Wrong: " + e);Program.ServerSocket.AddDelSocket(this); // 解析错误,也认为把消息断开}}private void MessageHandle(object? state){if (state == null) return;var msg = (INetMessage) state;if (msg is PlayerMessage playerMsg){Console.WriteLine($"Receive message from client {_socket} (ID {Id}): {playerMsg}");}else if (msg is QuitMessage quitMsg){Program.ServerSocket.AddDelSocket(this); // 客户端断开连接}else if (msg is HeartMessage heartMsg){_frontTime = DateTime.Now.Ticks / TimeSpan.TicksPerSecond;Console.WriteLine($"Receive heart message from client {_socket} (ID {Id}): {heartMsg}");}}private void HandleReceiveMessage(byte[] receiveBytes, int receiveNum){var messageId = 0;var index     = 0;// 收到消息时看之前有没有缓存// 如果有,直接拼接到后面receiveBytes.CopyTo(_cacheBytes, _cacheBytesLength);_cacheBytesLength += receiveNum;while (true){var messageLength = -1;// 处理前置信息if (_cacheBytesLength - index >= 8){// 解析 IdmessageId =  BitConverter.ToInt32(_cacheBytes, index);index     += sizeof(int);// 解析长度messageLength =  BitConverter.ToInt32(_cacheBytes, index);index         += sizeof(int);}// 处理消息体if (messageLength != -1 && _cacheBytesLength - index >= messageLength){// 解析消息体INetMessage message = default;switch (messageId){case 1001:message = new PlayerMessage();message.FromBytes(_cacheBytes, index);break;case 1003:message = new QuitMessage();message.FromBytes(_cacheBytes, index);break;case 999:message = new HeartMessage();message.FromBytes(_cacheBytes, index);break;}if (message != default){ThreadPool.QueueUserWorkItem(MessageHandle, message);}index += messageLength;// 如果消息体长度等于缓存长度,证明缓存已经处理完毕if (index == _cacheBytesLength){_cacheBytesLength = 0;break;}}else // 消息体还没有接收完毕{// 解析了前置信息,但是没有成功解析消息体if (messageLength != -1){index -= 8; // 回退到解析 Id 的位置}// 缓存剩余的数据_cacheBytesLength -= index;Array.Copy(_cacheBytes, index, _cacheBytes, 0, _cacheBytesLength);break;}}}
}

测试

​ 启动服务器后,运行 Unity,服务器中可以定时收到心跳消息:

image-20250504093828255

​ 结束运行 Unity,等待 5s 后,可看到服务器显示断开连接:

image-20250504095602541
http://www.dtcms.com/wzjs/245948.html

相关文章:

  • 网站建设专员做网站的公司哪家好
  • 做外贸哪个网站比较好seminar是什么意思
  • 网站定制与模板开发网络推广平台软件
  • 中介app开发制作公司整站seo技术搜索引擎优化
  • 怎样注册自己的微信小程序专业优化网站排名
  • 泗阳城乡建设局网站网络事件营销案例
  • 网站后台更新 前台不显示长沙seo推广
  • 安阳网站建设_宝塔建站系统
  • 在韶关做网站seo超级外链工具
  • 无锡做网站、广安seo外包
  • wordpress home url西安seo优化培训机构
  • 网站优化关键词怎么做搜索引擎推广有哪些平台
  • 制作网站网页设计世界羽联最新排名
  • 昆明做网站的搜索引擎优化方法有哪几种
  • wordpress做商城网站吗长沙百度快照优化排名
  • 做废旧金属的网站营销渠道分为三种模式
  • 晋城做网站公司企业查询系统官网
  • 免费发布信息网站seo网站推广平台
  • 如何进行网站关键词优化拓客公司联系方式
  • 上海网站制作公司是什么seo服务建议
  • 融资网站建设重点营销推广48个方法
  • 做地铁系统集成的公司网站网络运营推广怎么做
  • 个人网站建站步骤app接入广告变现
  • 蓝色扁平化企业网站故事式软文范例100字
  • 建站赚钱灰色抖音seo怎么做的
  • 最新钓鱼网站源码深圳靠谱网站建设公司
  • 沈阳网站建设方法手机网站制作平台
  • 做视频网站带宽要百度竞价系统
  • win7 添加asp网站百度搜索引擎属于什么引擎
  • 百度网站前三名权重一般在多少百度 指数