C#实现异步阻塞TCP(Send,Receive,Accept,Connect)
1.类
(1)服务器端操作类
public class TcpServiceSocket
{
//接收数据事件
public Action<Socket, string> recvMessageEvent = null;
//发送结果事件
public Action<int> sendResultEvent = null;
//允许连接到tcp服务器的tcp客户端数量
private int numConnections = 0;
//连接socket
private Socket listenSocket = null;
//tcp服务器ip
private string host = "";
//tcp服务器端口
private int port = 0;
//控制tcp客户端连接数量的信号量
private Semaphore maxNumberAcceptedClients = null;
private int bufferSize = 1024;
private List<Socket> clientSockets = null; public TcpServiceSocket(string host, int port, int numConnections)
{
if (string.IsNullOrEmpty(host))
throw new ArgumentNullException("host cannot be null");
if (port < 1 || port > 65535)
throw new ArgumentOutOfRangeException("port is out of range");
if (numConnections <= 0 || numConnections > int.MaxValue)
throw new ArgumentOutOfRangeException("_numConnections is out of range"); this.host = host;
this.port = port;
this.numConnections = numConnections;
clientSockets = new List<Socket>();
maxNumberAcceptedClients = new Semaphore(numConnections, numConnections);
} public void Start()
{
try
{
listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(new IPEndPoint(IPAddress.Parse(host), port));
listenSocket.Listen(numConnections);
AcceptAsync();
}
catch (Exception)
{
}
} private async void AcceptAsync()
{
await Task.Run(new Action(() =>
{
while (true)
{
maxNumberAcceptedClients.WaitOne(); try
{
Socket acceptSocket = listenSocket.Accept();
if (acceptSocket == null)
continue; clientSockets.Add(acceptSocket);
RecvAsync(acceptSocket);
}
catch (Exception)
{
maxNumberAcceptedClients.Release();
}
}
}));
} private async void RecvAsync(Socket acceptSocket)
{
await Task.Run(new Action(() =>
{
int len = 0;
byte[] buffer = new byte[bufferSize]; try
{
while ((len = acceptSocket.Receive(buffer, bufferSize, SocketFlags.None)) > 0)
{
if (recvMessageEvent != null)
recvMessageEvent(acceptSocket, Encoding.UTF8.GetString(buffer, 0, len));
}
}
catch (Exception)
{
CloseClientSocket(acceptSocket);
}
}));
} public async void SendAsync(Socket acceptSocket, string message)
{
await Task.Run(new Action(() =>
{
int len = 0;
byte[] buffer = Encoding.UTF8.GetBytes(message);
try
{
if ((len = acceptSocket.Send(buffer, buffer.Length, SocketFlags.None)) > 0)
{
if (sendResultEvent != null)
sendResultEvent(len);
}
}
catch (Exception)
{
CloseClientSocket(acceptSocket);
}
}));
} public async void SendMessageToAllClientsAsync(string message)
{
await Task.Run(new Action(() =>
{
foreach (var socket in clientSockets)
{
SendAsync(socket, message);
}
}));
} private void CloseClientSocket(Socket acceptSocket)
{
try
{
acceptSocket.Shutdown(SocketShutdown.Both);
}
catch { }
try
{
acceptSocket.Close();
}
catch { } maxNumberAcceptedClients.Release();
} public void CloseAllClientSocket(Socket acceptSocket)
{
try
{
foreach (var socket in clientSockets)
{
socket.Shutdown(SocketShutdown.Both);
}
}
catch { }
try
{
foreach (var socket in clientSockets)
{
socket.Close();
}
}
catch { } try
{
listenSocket.Shutdown(SocketShutdown.Both);
}
catch { }
try
{
listenSocket.Close();
}
catch { } try
{
maxNumberAcceptedClients.Release(clientSockets.Count);
clientSockets.Clear();
}
catch { }
}
}
(2)客户端操作类
public class TcpClientSocket
{
//接收数据事件
public Action<string> recvMessageEvent = null;
//发送结果事件
public Action<int> sendResultEvent = null;
//连接socket
private Socket connectSocket = null;
//tcp服务器ip
private string host = "";
//tcp服务器端口
private int port = 0;
private int bufferSize = 1024; public TcpClientSocket(string host, int port)
{
if (string.IsNullOrEmpty(host))
throw new ArgumentNullException("host cannot be null");
if (port < 1 || port > 65535)
throw new ArgumentOutOfRangeException("port is out of range"); this.host = host;
this.port = port;
} public void Start()
{
try
{
connectSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
connectSocket.Connect(host, port);
RecvAsync();
}
catch (Exception)
{
}
} private async void RecvAsync()
{
await Task.Run(new Action(() =>
{
int len = 0;
byte[] buffer = new byte[bufferSize];
try
{
while ((len = connectSocket.Receive(buffer, bufferSize, SocketFlags.None)) > 0)
{
if (recvMessageEvent != null)
recvMessageEvent(Encoding.UTF8.GetString(buffer, 0, len));
}
}
catch (Exception)
{
Restart();
}
}));
} public async void SendAsync(string message)
{
await Task.Run(new Action(() =>
{
int len = 0;
byte[] buffer = Encoding.UTF8.GetBytes(message);
try
{
if ((len = connectSocket.Send(buffer, buffer.Length, SocketFlags.None)) > 0)
{
if (sendResultEvent != null)
sendResultEvent(len);
}
}
catch (Exception)
{
Restart();
}
}));
} public void CloseClientSocket()
{
try
{
connectSocket.Shutdown(SocketShutdown.Both);
}
catch { }
try
{
connectSocket.Close();
}
catch { }
} public void Restart()
{
CloseClientSocket();
Start();
} }
2.使用
(1)服务器:
public partial class Form1 : Form
{
TcpServiceSocket tcpServiceSocket = null;
private readonly string ip = "192.168.172.142";
private readonly int port = 8090; public Form1()
{
InitializeComponent();
tcpServiceSocket = new TcpServiceSocket(ip, port, 10);
tcpServiceSocket.recvMessageEvent += new Action<Socket, string>(Recv);
} private void Recv(Socket socket, string message)
{
this.BeginInvoke(new Action(() =>
{
tbRecv.Text += message + "\r\n";
}));
} private void btnStart_Click(object sender, EventArgs e)
{
tcpServiceSocket.Start();
} private void btnSend_Click(object sender, EventArgs e)
{
string message = tbSend.Text.Trim();
if (string.IsNullOrEmpty(message))
return; tcpServiceSocket.SendMessageToAllClientsAsync(message);
tbSend.Text = "";
}
}
(2)客户端
public partial class Form1 : Form
{
private TcpClientSocket tcpClientSocket = null;
private readonly string ip = "192.168.172.142";
private readonly int port = 8090; public Form1()
{
InitializeComponent();
tcpClientSocket = new TcpClientSocket(ip, port);
tcpClientSocket.recvMessageEvent += new Action<string>(Recv);
} private void Recv(string message)
{
this.BeginInvoke(new Action(() =>
{
tbRecv.Text += message + "\r\n";
}));
} private void btnStart_Click(object sender, EventArgs e)
{
tcpClientSocket.Start();
} private void btnSend_Click(object sender, EventArgs e)
{
string message = tbSend.Text.Trim();
if (string.IsNullOrEmpty(message))
return; tcpClientSocket.SendAsync(message);
tbSend.Text = "";
}
}
C#实现异步阻塞TCP(Send,Receive,Accept,Connect)的更多相关文章
- C#实现异步阻塞TCP(SocketAsyncEventArgs,SendAsync,ReceiveAsync,AcceptAsync,ConnectAsync)
1.类 (1)socket IO操作内存管理类 BufferManager // This class creates a single large buffer which can be divid ...
- {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll
Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...
- GIL 线程池 进程池 同步 异步 阻塞 非阻塞
1.GIL 是一个全局解释器锁,是一种互斥锁 为什么需要GIL锁:因为一个python.exe进程中只有一份解释器,如果这个进程开启了多个线程都要执行代码 多线程之间要竞争解释器,一旦竞争就有可能出现 ...
- 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
[Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...
- python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)
9.11 进程池与线程池 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 池子内什么时候装进程:并发的任务属于计算密集型 池子内什么时候装线程:并发的任务属于I ...
- 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor
开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...
- 操作系统介绍-操作系统历史,IO,进程的三态,同步异步阻塞非阻塞
1.操作系统历史 2.进程,IO,同步异步阻塞非阻塞 操作系统历史: 手工操作: 1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式.此时还没有操作系统的概念. 手工操 ...
- 【Linux 网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数:对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...
- [TCP/IP]TCP服务端accept发生在三次握手的哪一个阶段
TCP服务端accept发生在三次握手之后 客户端socket()==>connect()==>write()==>read()服务端socket()==>bind()==&g ...
随机推荐
- VSCode 怎么运行代码
VSCode 怎么运行代码,集成终端和资源管理器也有互动.比如我们打开了一个脚本文件,希望直接执行这个脚本文件,就可以打开命令面板,运行 “在活动终端中运行活动文件”(Run Active File ...
- OpenCV_CS.测试
1.在C#中使用OpenCV(使用OpenCVSharp) - jsxyhelu - 博客园.html(https://www.cnblogs.com/jsxyhelu/p/9669583.html) ...
- STM32 MCU一次计算优化和提速
1.背景 STM32 MCU对25.6Kb数据进行压缩,丢掉每个数据的低4位然后2个字节拼接为1个字节.发现处理耗时竞达1ms以上,于是开始进行优化,最后达到200us的效果,提速5倍以上. 2.优化 ...
- elasticsearch安装ik
https://github.com/medcl/elasticsearch-analysis-ik/releases下载对应的ik plugins/目录下创建analysis-ik,再将上述中的zi ...
- linux_mysql学习系列
Linux&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 网站架构系列文章:http://www.cnblogs.co ...
- 1.5JdbcTmeplates、Jpa、Mybatis、beatlsql、Druid的使用
Spring boot 连接数据库整合 -- create table `account`DROP TABLE `account` IF EXISTSCREATE TABLE `account` ( ...
- 三分钟搞定Python中的装饰器
python的装饰器是python的特色高级功能之一,言简意赅得说,其作用是在不改变其原有函数和类的定义的基础上,给他们增添新的功能. 装饰器存在的意义是什么呢?我们知道,在python中函数可以调用 ...
- VS2017生成一个简单的DLL文件 和 LIB文件——C语言
下面我们将用两种不同的姿势来用VS2017生成dll文件(动态库文件)和lib文件(静态库文件),这里以C语言为例,用最简单的例子,来让读者了解如何生成dll文件(动态库文件) 生成动态库文件 姿势一 ...
- ButterKnife8.5.1最新版本使用详细步骤
android studio中使用方法: 1.build.gradle(Modul: app) 添加dependencies{ compile 'com.jakewharton:butterknife ...
- c# 自定义解析JSON字符串数据
解析json字符串有很多方式, 1 : 在网上下载json解析的dll类库并添加引用, 调用相关方法; 2 : 使用自带类库JavaScriptSerializer的序列号和反序列化; 对于以上两个方 ...