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)的更多相关文章

  1. C#实现异步阻塞TCP(SocketAsyncEventArgs,SendAsync,ReceiveAsync,AcceptAsync,ConnectAsync)

    1.类 (1)socket IO操作内存管理类 BufferManager // This class creates a single large buffer which can be divid ...

  2. {Python之进程} 背景知识 什么是进程 进程调度 并发与并行 同步\异步\阻塞\非阻塞 进程的创建与结束 multiprocess模块 进程池和mutiprocess.Poll

    Python之进程 进程 本节目录 一 背景知识 二 什么是进程 三 进程调度 四 并发与并行 五 同步\异步\阻塞\非阻塞 六 进程的创建与结束 七 multiprocess模块 八 进程池和mut ...

  3. GIL 线程池 进程池 同步 异步 阻塞 非阻塞

    1.GIL 是一个全局解释器锁,是一种互斥锁 为什么需要GIL锁:因为一个python.exe进程中只有一份解释器,如果这个进程开启了多个线程都要执行代码 多线程之间要竞争解释器,一旦竞争就有可能出现 ...

  4. 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    [Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...

  5. python 之 并发编程(进程池与线程池、同步异步阻塞非阻塞、线程queue)

    9.11 进程池与线程池 池子使用来限制并发的任务数目,限制我们的计算机在一个自己可承受的范围内去并发地执行任务 池子内什么时候装进程:并发的任务属于计算密集型 池子内什么时候装线程:并发的任务属于I ...

  6. 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor

    开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...

  7. 操作系统介绍-操作系统历史,IO,进程的三态,同步异步阻塞非阻塞

    1.操作系统历史 2.进程,IO,同步异步阻塞非阻塞 操作系统历史: 手工操作: 1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式.此时还没有操作系统的概念. 手工操 ...

  8. 【Linux 网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: connect()函数:对于客户端的 connect() 函数,该函数的功能为客户端主动连接服务器,建立连接是通过三 ...

  9. [TCP/IP]TCP服务端accept发生在三次握手的哪一个阶段

    TCP服务端accept发生在三次握手之后 客户端socket()==>connect()==>write()==>read()服务端socket()==>bind()==&g ...

随机推荐

  1. hi cnblogs

    hi cnblogs 前言: 作为一个工作好些年的it男,还没正经写过技术博客,真是太羞愧了... 正文: 先扯点儿虚的,无论从事什么行业,最重要的都是自我认知和自我定位.至今,我也有工作了小五年了, ...

  2. spring boot中Elasticsearch默认版本问题

    这是今天遇上的一个问题. 添加的依赖是7.2.0版本的Elasticsearch,但是其中有两项是6.4.3的,导致我从其他地方移植过来的代码报错. 据大神说,这是因为spring boot中默认的E ...

  3. vue v-slot

    参考链接:https://www.jianshu.com/p/7020636d68a5

  4. BootStrap Table方法使用小结

    参考链接:https://www.cnblogs.com/Amaris-Lin/p/7797920.html

  5. oauth2中org.springframework.security.core.userdetails.User无法转换为封装的AuthorizationInfoBean

    用springboot + oauth2 + redis搭建了一个项目,创建一个自定义的AuthorizationInfoBean继承org.springframework.security.core ...

  6. poj2318(叉积判断点在直线左右+二分)

    题目链接:https://vjudge.net/problem/POJ-2318 题意:有n条线将矩形分成n+1块,m个点落在矩形内,求每一块点的个数. 思路: 最近开始肝计算几何,之前的几何题基本处 ...

  7. [转帖]K8s 学习者绝对不能错过的最全知识图谱(内含 58个知识点链接)

    K8s 学习者绝对不能错过的最全知识图谱(内含 58个知识点链接)   https://www.cnblogs.com/alisystemsoftware/p/11429164.html 需要加强学习 ...

  8. oracle不记得所有账户和密码怎么办

    1.打开cmd,输入sqlplus /nolog,回车: 2.输入“conn / as sysdba”; 3.输入“alter user sys identified by 新密码:”,注意:必须输入 ...

  9. [翻译] 深入浅出Go语言调度器:第一部分 - 系统调度器

    目录 译者序 序 介绍 系统调度器 执行指令 Figure 1 Listing 1 Listing 2 Listing 3 线程状态 任务侧重 上下文切换 少即是多 寻找平衡 缓存行 Figure 2 ...

  10. Proxy 和aop

    Proxy 就是代理,意思就是 你不用去做,别人代替你去处理 先来个静态代理 public interface Hello { void say(String name); } 被代理类 public ...