最近在园子里看了大神写的(面试官,不要再问我三次握手和四次挥手),忍不住写段程序来测试一番。

    在网上找了很多例子,大多只实现了TCP点对点通讯,但实际应用中,一个服务器端口往往要监听多个客户端发来的消息。

测试工具下载:https://download.csdn.net/download/nbyanghuichao/11872360

    本例采用System.Threading实现多线程监听,下面只介绍核心代码,省略了消息提示和错误处理,可以从我的GitHub获取完整代码:https://github.com/FB208/CodeSpace/tree/master/CodeSpace.CSharp/TCP.Client

数据声明:

private string _ip;//IP
private int _port;//端口
//客户端集合
public static List<TcpClientModel> clients = new List<TcpClientModel>
private static byte[] bytes = new byte[1024 * 100];
/// <summary>
/// 用于存储客户端
/// </summary>
public class TcpClientModel
{
/// <summary>
/// IP:Port
/// </summary>
public string RemoteEndPoint { get; set; }
/// <summary>
/// 客户端链接对象
/// </summary>
public TcpClient TcpClient { get; set; }
}

启动监听:

///启动监听
void Init()
{
try
{
IPAddress ip = IPAddress.Parse(_ip);
int port = _port;
TcpListener listener = new TcpListener(ip, port);
//启动监听
listener.Start();
tb_console.AppendText($"Listener...\r\n");
//异步接收 递归循环接收多个客户端
listener.BeginAcceptTcpClient(new AsyncCallback(GetAcceptTcpclient), listener);
}
catch (Exception ex)
{ }
}

接收客户端:

private void GetAcceptTcpclient(IAsyncResult State)
{
//处理多个客户端接入
    TcpListener listener = (TcpListener)State.AsyncState;
//接收到客户端请求
TcpClient client = listener.EndAcceptTcpClient(State);
//保存到客户端集合中
clients.Add(new TcpClientModel() { TcpClient = client, RemoteEndPoint = client.Client.RemoteEndPoint.ToString() });     //开启线程用来持续接收来自客户端的数据
Thread myThread = new Thread(() =>
{
ReceiveMsgFromClient(client);
});
myThread.Start();
listener.BeginAcceptTcpClient(new AsyncCallback(GetAcceptTcpclient), listener);
}

接收消息并响应客户端:

private void ReceiveMsgFromClient(object reciveClient)
{
TcpClient client = reciveClient as TcpClient;
if (client == null)
{
return;
}
while (true)
{
try
{
NetworkStream stream = client.GetStream();
int num = stream.Read(bytes, 0, bytes.Length); //将数据读到result中,并返回字符长度                  
            if (num != 0)
{
//把字节数组中流存储的数据以字符串方式赋值给str
//这里就是接收到的客户端消息
string str = Encoding.UTF8.GetString(bytes, 0, num);                //给客户端返回一个消息
                string msg = "Your message has been received by the server[" + str + "]"; bool result = TCPHelper.SendToClient(client, msg, out msg);
if (!result)
{
//发送失败
}
}
else
{  
//这里需要注意 当num=0时表明客户端已经断开连接,需要结束循环,不然会死循环一直卡住
break;
}
}
catch (Exception ex)
{
//链接失败 从集合中移除出错客户端
clients.Remove(clients.FirstOrDefault(m => m.RemoteEndPoint == client.Client.RemoteEndPoint.ToString()));
break;
} }
}

从服务器向客户端发送消息的工具类:

public static class TCPHelper
{
public static bool SendToClient(TcpClient client, string message,out string errorMsg)
{
try
{
byte[] bytes = new byte[1024 * 100];
bytes = Encoding.UTF8.GetBytes(message);
NetworkStream stream = client.GetStream();
stream.Write(bytes, 0, bytes.Length);
stream.Flush();
errorMsg = "";
return true;
}
catch (Exception ex)
{
errorMsg = ex.Message;
return false;
}
}
}

测试效果:

完整代码请关注:https://github.com/FB208/CodeSpace/tree/master/CodeSpace.CSharp/TCP.Client

.Net TCP探索(一)——TCP服务端开发(同时监听多个客户端请求)的更多相关文章

  1. TCP状态机:当服务端主动发FIN进TIME_WAIT,客户端源端口复用会发生什么

    0X01 正常情况下TCP连接会通过4次挥手进行拆链(也有通过RST拆除连接的可能,见为什么服务器突然回复RST--小心网络中的安全设备),下图TCP状态机展示了TCP连接的状态变化过程: 我们重点看 ...

  2. 自己封装的Socket组件,实现服务端多进程共享Socket对象,协同处理客户端请求

    DotNet.Net.MySocket是SLB.NET(Server Load Balance服务器负载均衡)项目中的核心组件. 在实际的项目中发现,单进程的服务端处理高并发的客户请求能力有限. 所以 ...

  3. python网络编程TCP服务多客户端的服务端开发

    #服务多客户端TCP服务端开发 2 #方法说明 3 """ 4 bind(host,port)表示绑定端口号,host是ip地址,ip地址一般不进 行绑定,表示本机的任何 ...

  4. 网络编程之TCP客户端开发和TCP服务端开发

    开发 TCP 客户端程序开发步骤 创建客户端套接字对象 和服务端套接字建立连接 发送数据 接收数据 关闭客户端套接字 import socket if __name__ == '__main__': ...

  5. 异步tcp通信——APM.Core 服务端概述

    为什么使用异步 异步线程是由线程池负责管理,而多线程,我们可以自己控制,当然在多线程中我们也可以使用线程池.就拿网络扒虫而言,如果使用异步模式去实现,它使用线程池进行管理.异步操作执行时,会将操作丢给 ...

  6. TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q

    TCP协议下的服务端并发,GIL全局解释器锁,死锁,信号量,event事件,线程q 一.TCP协议下的服务端并发 ''' 将不同的功能尽量拆分成不同的函数,拆分出来的功能可以被多个地方使用 TCP服务 ...

  7. java 网络编程基础 TCP/IP协议:服务端ServerSocket;客户端Socket; 采用多线程方式处理网络请求

    1.Java中客户端和服务器端通信的简单实例 Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一 ...

  8. socket服务端开发之测试使用threading和gevent框架

    socket服务端开发之测试使用threading和gevent框架 话题是测试下多线程和gevent在socket服务端的小包表现能力,测试的方法不太严谨,也没有用event loop + pool ...

  9. 俯瞰 Java 服务端开发

    原文首发于 github ,欢迎 star . Java 服务端开发是一个非常宽广的领域,要概括其全貌,即使是几本书也讲不完,该文将会提到许多的技术及工具,但不会深入去讲解,旨在以一个俯瞰的视角去探寻 ...

随机推荐

  1. 全网最实用的 Debug调试技巧汇总-Python大佬偷偷使用的神技

    一.思考❓❔ 1.什么是debug? 找茬 找软件的茬 发现程序的缺陷 2.为什么需要debug? 谁都不敢保证,写的代码没有任何问题 高效查找软件异常 一位优秀的开发工程师 20%的时间写代码 80 ...

  2. 编写一个函数来找出所有不带歧义的函数名,也就是 那些只在一个模块里出现过的函数名(erlang)

    erlang程序设计第八章练习题第二题: code:all_loaded()命令会返回一个由{Mod,File}对构成的列表,内含所有Erlang系统 载入的模块.使用内置函数Mod:module_i ...

  3. Dijkstra算法的Java实现

    package main.java; import main.java.utils.GraphUtil; import java.util.ArrayDeque; import java.util.L ...

  4. Net基础篇_学习笔记_第十天_方法(函数)

    方法(函数): 函数就是将一堆代码进行重用的一种机制.//解决冗余代码问题------方法出现了.            面向对象的三大特征:封装.继承.多态 函数的语法:[public] stati ...

  5. spring 事务配置方式以及事务的传播性、隔离级别

    在前面的文章中总结了spring事务的5中配置方式,但是很多方式都不用而且当时的配置使用的所有参数都是默认的参数,这篇文章就看常用的两种事务配置方式并信息配置事务的传播性.隔离级别.以及超时等问题,废 ...

  6. 【学习笔记】第二章 python安全编程基础---正则表达式

    一.python正则表达式 定义:正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式相匹配: 1.1RE模块:是python语言拥有全部的正则表达式功能的一个正则模块: 常见 ...

  7. 降低 80% 的读写响应延迟!我们测评了 etcd 3.4 新特性(内含读写发展史)

    作者 | 陈洁(墨封)  阿里云开发工程师 导读:etcd 作为 K8s 集群中的存储组件,读写性能方面会受到很多压力,而 etcd 3.4 中的新特性将有效缓解压力,本文将从 etcd 数据读写机制 ...

  8. 第1次作业:使用Packet Tracer分析HTTP数据包

    个人信息:      •  姓名:李微微       •  班级:计算1811       •  学号:201821121001 一.摘要 本文将会描述使用Packet Tracer工具用到的网络结构 ...

  9. Kubernetes 从懵圈到熟练:集群服务的三个要点和一种实现

    作者 | 声东 阿里云售后技术专家 文章来源:Docker,点击查看原文. 以我的经验来讲,理解 Kubernetes 集群服务的概念,是比较不容易的一件事情.尤其是当我们基于似是而非的理解,去排查服 ...

  10. WordPress安全防护攻略

    个人近期做了一个WordPress站点,目前处于内测阶段,虽然公网还没部署起来,但是先在这学习整理一下安全防护的问题. 第一:及时更新WordPress 由于33%的互联网都在使用WordPress站 ...