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. eNSP——ARP及ProxyARP

    原理: ARP (Address Resolution Protocol)是用来将IP地址解析为MAC地址的协议.ARP表项可以分为动态和静态两种类型.动态ARP是利用ARP广播报文,动态执行并自动进 ...

  2. Python Requests库 form-data 上传文件操作

    请求数据示例: ------WebKitFormBoundaryKLoWgrA4O40MayHM Content-Disposition: form-data; name="id" ...

  3. [转帖]linux命令dd

    linux命令dd   dd 是diskdump 的含义 之前学习过 总是记不住 用的还是少. http://embeddedlinux.org.cn/emb-linux/entry-level/20 ...

  4. 【Funny Things】001——QQ循环发送消息

    借用Java的Robot类库中的键鼠模拟的方法,执行这个操作,首先切换到QQ界面,然后循环粘贴,回车发送消息. package newtest; import java.awt.*; import j ...

  5. 剑指offer42:数组和一个数字S,输出两个数的乘积最小的

    1 题目描述 输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的. 输出描述: 对应每个测试案例,输出两个数,小的先输出. ...

  6. POJ 1015 Jury Compromise (记录路径的背包问题)

    (点击此处查看原题) 题意 为了审判某一个人,需要在n个人当中选出m个人组成陪审团,n个人中每个人都有作为起诉方的价值p和作为辩护方的价值d,为了保证公平性,要求m个人作为起诉方的价值之和P和作为辩护 ...

  7. PHP学习之PHP的语法糖

    PHP的语法糖 计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用.  常见的PHP的语法糖 echo(),print(),die(),isset(),unset(),i ...

  8. hadoop 》》 django 简单操作hdfs 语句

    >> from django.shortcuts import render # Create your views here. from hdfs.client import Clien ...

  9. Spring集成kafka,消费者运行时内存占用会一直增长

    Spring集成kafka,消费者运行时内存占用会一直增长? 20C 本人用Spring集成kafka消费者,发布运行时内存占用会一直升高,最后程序挂掉.请各位大神看看,提供解决方法 以下是我的配置文 ...

  10. StoneTab标签页CAD插件 3.2.1

    //////////////////////////////////////////////////////////////////////////////////////////////////// ...