C# Tcplistener,Tcp服务端简易封装

文章目录

  • 前言
  • 相关文章
  • 前言
  • 设计
  • 代码
  • 简单使用
  • 运行结果

前言

我最近有个需求要写Tcp服务端,我发现Tcp服务端的回调函数比较麻烦,简化Tcp的服务,我打算自己封装一个简单的Tcp服务端。

相关文章

C# TCP应用编程三 异步TCP应用编程

C# Tcpclient Tcplistener 服务器接收多个客户端消息通讯

关于C#Socket断开重连问题

前言

我最近有个Tcp服务端的项目,发现TcpListener 服务端官方写起来很麻烦。而且没有回调函数。现在做个简单的服务端封装

设计

TcpServerService
ShowMsg:打印消息
AddClient_CallBack:新增Tcp客户端回调函数
SendMsg/ReceiveMsg:Tcp客户端发送接受回调
Clients:Tcp客户端集合,连接增加,断开去除
其它函数

代码

 public class TcpServeService
{public string Ip { get; set; }public int Port { get; set; }public TcpListener Server { get; set; }public List<TcpClient> Clients { get; set; }/// <summary>/// 客户端添加回调函数,如果要重写通讯逻辑需要覆盖/// </summary>public Action<TcpClient> AddClient_CallBack { get; set; }public Action<string> ShowMsg { get; set; }/// <summary>/// 默认自动回复Tcp服务端/// </summary>/// <param name="ip"></param>/// <param name="port"></param>public TcpServeService(string ip, int port){Clients = new List<TcpClient>();ShowMsg = (msg) => Console.WriteLine(msg);AddClient_CallBack = (client) => AutoSendBack(client);this.Ip = ip;this.Port = port;Server = new TcpListener(IPAddress.Parse(ip), port);}/// <summary>/// Tcp添加Client回调/// </summary>/// <param name="ar"></param>private void DoAcceptTcpclient(IAsyncResult ar){// Get the listener that handles the client request.TcpListener listener = (TcpListener)ar.AsyncState;// End the operation and display the received data on // the console.TcpClient client = listener.EndAcceptTcpClient(ar);Clients.Add(client);// Process the connection here. (Add the client to a// server table, read data, etc.)ShowMsg($"Tcp客户端连接成功!,当前连接数{Clients.Count},Id[{client.Client.RemoteEndPoint.ToString()}]");AddClient_CallBack(client);//开启线程用来不断接收来自客户端的数据Server.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpclient), Server);}/// <summary>/// 移除Tcp客户端/// </summary>/// <param name="client"></param>public void RemoveClient(TcpClient client){NetworkStream stream = client.GetStream();ShowMsg($"Tcp客户端连接断开!,当前连接数{Clients.Count},Id[{client.Client.RemoteEndPoint.ToString()}]");stream.Close();client.Close();Clients.Remove(client);}/// <summary>/// 启动Tcp服务/// </summary>public void Start(){Server.Start();Server.BeginAcceptTcpClient(new AsyncCallback(DoAcceptTcpclient), Server);ShowMsg($"Tcp服务端启动成功!IP[{Ip}],Port[{Port}]");}/// <summary>/// 返回数据/// </summary>/// <param name="Str"></param>/// <param name="Bytes"></param>public record TcpData(string Str, byte[] Bytes);/// <summary>/// 同步阻塞读取数据/// </summary>/// <param name="client"></param>/// <returns></returns>public static TcpData ReadMsg(TcpClient client){NetworkStream networkStream = client.GetStream();var resBytes = new byte[client.ReceiveBufferSize];var num = networkStream.Read(resBytes, 0, resBytes.Length);resBytes = resBytes.Take(num).ToArray();var resStr = UnicodeEncoding.ASCII.GetString(resBytes);if (!IsConnect(client)){throw new Exception($"{client.Client.RemoteEndPoint?.ToString()}Tcp连接已断开");}return new TcpData(resStr,resBytes);}/// <summary>/// 发送Ascll数据/// </summary>/// <param name="tcpClient"></param>/// <param name="msg"></param>public static void SendMsg(TcpClient tcpClient, string msg){byte[] arrSendMsg = Encoding.UTF8.GetBytes(msg);SendMsg(tcpClient, arrSendMsg);}/// <summary>/// Tcp客户端连接是否断开/// </summary>/// <param name="tcpClient"></param>/// <returns></returns>public static bool IsConnect(TcpClient tcpClient){if (tcpClient.Client.Poll(1, SelectMode.SelectRead) && tcpClient.Available == 0){return false;}else { return true; }}/// <summary>/// 发送Bytes[]数据/// </summary>/// <param name="tcpClient"></param>/// <param name="msg"></param>public static void SendMsg(TcpClient tcpClient, byte[] msg){NetworkStream networkStream = tcpClient.GetStream();networkStream.Write(msg, 0, msg.Length);}/// <summary>/// 发送并返回数据/// </summary>/// <param name="tcpClient"></param>/// <param name="msg"></param>/// <returns></returns>public static TcpData SendAndReceive(TcpClient tcpClient,string msg){SendMsg(tcpClient,msg);return ReadMsg(tcpClient);}public static TcpData SendAndReceive(TcpClient tcpClient, byte[] msg){SendMsg(tcpClient, msg);return ReadMsg(tcpClient);}/// <summary>/// 默认自动回复,异常捕捉/// </summary>/// <param name="tcpClient"></param>/// <param name="timeOut">超时时间</param>/// <returns></returns>public async Task AutoSendBack(TcpClient tcpClient, int timeOut = 10 * 1000){//超时时间tcpClient.ReceiveTimeout = timeOut;tcpClient.SendTimeout = timeOut;while (true){try{if (!Clients.Contains(tcpClient)){throw new Exception("Tcp客户端已被移除!");}var receive = ReadMsg(tcpClient);ShowMsg($"TcpClient[{tcpClient.Client.RemoteEndPoint?.ToString()}]:收到数据{receive.Str}");SendMsg(tcpClient, receive.Str);}catch (Exception ex){RemoveClient(tcpClient);ShowMsg("发送失败");ShowMsg(ex.Message);}}}}

简单使用

//对tcpServeService进行了默认配置,默认自动回复,自动维护Client集合
TcpServeService tcpServeService = new TcpServeService("192.168.100.21", 10003);//如果想要自定义回复,需要覆盖AddClient_CallBack函数,使用异步任务处理连接
//tcpServeService.AddClient_CallBack = ((client) => {
//    Task.Run(() =>
//    {
//        //你的客户端连接异步任务
//    });
//});//如果想要打印在Winfrom/WPF的界面,覆盖此回调
//tcpServeService.ShowMsg = (msg) =>
//{
//    //你的消息打印函数
//};
//tcpServeService.Start();
tcpServeService.Start();

运行结果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/285961.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux本地搭建StackEdit Markdown编辑器结合内网穿透实现远程访问

文章目录 1. docker部署Stackedit2. 本地访问3. Linux 安装cpolar4. 配置Stackedit公网访问地址5. 公网远程访问Stackedit6. 固定Stackedit公网地址 StackEdit是一个受欢迎的Markdown编辑器&#xff0c;在GitHub上拥有20.7k Star&#xff01;&#xff0c;它支持将Markdown笔记保…

【MATLAB第83期】基于MATLAB的LSTM代理模型的SOBOL全局敏感性运用

【MATLAB第83期】基于MATLAB的LSTM代理模型的SOBOL全局敏感性运用 引言 在前面几期&#xff0c;介绍了敏感性分析法&#xff0c;本期来介绍lstm作为代理模型的sobol全局敏感性分析模型。 【MATLAB第31期】基于MATLAB的降维/全局敏感性分析/特征排序/数据处理回归问题MATLAB代…

Lazada商品详情API在电商中的价值及实时数据获取实践

一、引言 在电商行业&#xff0c;数据是驱动业务增长的关键。Lazada作为东南亚地区知名的电商平台&#xff0c;其商品详情API对于电商行业具有深远的影响。本文将探讨Lazada商品详情API在电商行业中的重要性&#xff0c;并介绍如何实现实时数据获取。 二、Lazada商品详情API的…

基于Java SSM框架实现高校信息资源共享平台系统【项目源码+论文说明】

基于java的SSM框架实现高校信息资源共享平台系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们…

部署threestudio | stable zero123

stable zero123的官网https://huggingface.co/stabilityai/stable-zero123 选择我在autodl的stable-zero123这个镜像&#xff0c;或者直接选这个基础环境 开机后切换到conda的base环境 这里注意一点就是目前stable-zero123这个镜像还没解决的问题&#xff0c;就是没法使用xfo…

大数据机器学习:从理论到实战,探索学习率的调整策略

大数据机器学习&#xff1a;从理论到实战&#xff0c;探索学习率的调整策略 全文目录 大数据机器学习&#xff1a;从理论到实战&#xff0c;探索学习率的调整策略一、引言二、学习率基础定义与解释学习率与梯度下降学习率对模型性能的影响 三、学习率调整策略常量学习率时间衰减…

时代变了,100多张报表自动生成,不用开发!

十多年老IT&#xff0c;现任职某大厂 毫不客气地说&#xff0c;别看某大厂看起来各种的高大上&#xff0c;其实内在信息化简直就是一团乱账&#xff0c;业务数据多&#xff0c;但都被按照不同指标和存储方式放在各自系统中&#xff1b;业务系统多&#xff0c;但数据孤岛严重&a…

【Unity】运行时创建曲线(贝塞尔的运用)

[Unity]运行时创建线&#xff08;贝塞尔的运用&#xff09; 1. 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线。 2. 原理介绍 2.1 曲线的创建 unity建立网格曲线可以参考Unity程序化网格体的实现方法。主要分为顶点&#xff0c;三角面&#xff0c…

基于ssm餐饮掌上设备点餐系统论文

餐饮掌上设备点餐系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了餐饮掌上设备点餐系统的开发全过程。通过分析餐饮掌上设备点餐系统管理的不足&#xff0c;创建了一个计算机管理餐饮掌上设备点餐系统的…

【LeetCode】每日一题 2023_12_19 寻找峰值 II(二分)

文章目录 刷题前唠嗑题目&#xff1a;寻找峰值 II题目描述代码与解题思路 刷题前唠嗑 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;寻找峰值 II 题目链接&#xff1a;1901. 寻找峰值 II 题目描述 代码与解题思路 除了暴力的 O(N^2) 找这…

TypeScript 中的高级类型(联合、交叉、泛型、映射类型)

文章目录 一、联合类型&#xff08;Union Types&#xff09;二、交叉类型&#xff08;Intersection Types&#xff09;三、泛型3.1 泛型结合extends3.2 泛型结合 keyof3.3 extends keyof 和 in keyof 的区别 四、条件类型&#xff08;Conditional Types&#xff09; TypeScript…

Zookeeper-快速开始

Zookeeper介绍 简介&#xff1a;ZooKeeper 是一个开源的分布式协调框架&#xff0c;是Apache Hadoop 的一个子项目&#xff0c;主要用来解决分布式集群中应用系统的一致性问题。 设计目标&#xff1a;将那些复杂且容易出错的分布式一致性服务封装起来&#xff0c;构成一个高效…