C#实现异步阻塞TCP
1.类
(1)socket IO操作内存管理类 BufferManager
// This class creates a single large buffer which can be divided up
// and assigned to SocketAsyncEventArgs objects for use with each
// socket I/O operation.
// This enables bufffers to be easily reused and guards against
// fragmenting heap memory.
//
// The operations exposed on the BufferManager class are not thread safe.
public class BufferManager
{
//buffer缓冲区大小
private int m_numBytes;
//缓冲区
private byte[] m_buffer;
private Stack<int> m_freeIndexPool;
private int m_currentIndex;
private int m_bufferSize;
public BufferManager(int totalBytes, int bufferSize)
{
m_numBytes = totalBytes;
m_currentIndex = 0;
m_bufferSize = bufferSize;
m_freeIndexPool = new Stack<int>();
}
/// <summary>
/// 给buffer分配缓冲区
/// </summary>
public void InitBuffer()
{
m_buffer = new byte[m_numBytes];
}
/// <summary>
/// 将buffer添加到args的IO缓冲区中,并设置offset
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
public bool SetBuffer(SocketAsyncEventArgs args)
{
if (m_freeIndexPool.Count > 0)
{
args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize);
}
else
{
if ((m_numBytes - m_bufferSize) < m_currentIndex)
{
return false;
}
args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize);
m_currentIndex += m_bufferSize;
}
return true;
}
/// <summary>
/// 将buffer从args的IO缓冲区中释放
/// </summary>
/// <param name="args"></param>
public void FreeBuffer(SocketAsyncEventArgs args)
{
m_freeIndexPool.Push(args.Offset);
args.SetBuffer(null, 0, 0);
}
/// <summary>
/// 释放全部buffer缓存
/// </summary>
public void FreeAllBuffer()
{
m_freeIndexPool.Clear();
m_currentIndex = 0;
m_buffer = null;
}
}
(2)SocketAsyncEventArgsPool
// Represents a collection of reusable SocketAsyncEventArgs objects.
public class SocketAsyncEventArgsPool
{
private Stack<SocketAsyncEventArgs> m_pool;
// Initializes the object pool to the specified size
//
// The "capacity" parameter is the maximum number of
// SocketAsyncEventArgs objects the pool can hold
public SocketAsyncEventArgsPool(int capacity)
{
m_pool = new Stack<SocketAsyncEventArgs>(capacity);
}
// Add a SocketAsyncEventArg instance to the pool
//
//The "item" parameter is the SocketAsyncEventArgs instance
// to add to the pool
public void Push(SocketAsyncEventArgs item)
{
if (item == null) { throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null"); }
lock (m_pool)
{
m_pool.Push(item);
}
}
// Removes a SocketAsyncEventArgs instance from the pool
// and returns the object removed from the pool
public SocketAsyncEventArgs Pop()
{
lock (m_pool)
{
return m_pool.Pop();
}
}
/// <summary>
/// 清空栈中元素
/// </summary>
public void Clear()
{
lock (m_pool)
{
m_pool.Clear();
}
}
// The number of SocketAsyncEventArgs instances in the pool
public int Count
{
get { return m_pool.Count; }
}
}
(3)AsyncUserToken
using System;
using System.Net;
using System.Net.Sockets;
namespace JCommon.Net
{
/// <summary>
/// 存储客户端信息, 这个可以根据自己的实际情况来定义
/// </summary>
public class AsyncUserToken
{
private Socket socket = null;
private IPEndPoint endPort = null;
private DateTime connectTime = default(DateTime); // 连接时间
public Socket Socket
{
get { return this.socket; }
set { this.socket = value; }
}
public DateTime ConnectTime
{
get { return this.connectTime; }
set { this.connectTime = value; }
}
public IPEndPoint EndPort
{
get { return this.endPort; }
set { this.endPort = value; }
}
}
}
(4)服务器端操作类SocketServer
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace JCommon.Net
{
public class SocketServer
{
public event EventHandler<SocketAsyncEventArgs> OnReceiveCompleted; // 接收到数据
public event EventHandler<SocketAsyncEventArgs> OnSendCompleted; // 数据发送完成
public event EventHandler<SocketAsyncEventArgs> OnAccept; // 客户端连接通知
public event EventHandler<SocketAsyncEventArgs> OnConnectionBreak; // 客户端下线通知
private readonly object m_lockHelper = new object();
private bool m_isRunning = false; // TCP服务器是否正在运行
private int m_numConnections = 1; // 同时处理的最大连接数
private int m_bufferSize = 0; // 用于每个Socket I/O 操作的缓冲区大小
private BufferManager m_bufferManager = null; // 表示用于所有套接字操作的大量可重用的缓冲区
private Socket listenSocket = null; // 用于监听传入的连接请求的套接字
private SocketAsyncEventArgsPool m_readWritePool = null; // 可重用SocketAsyncEventArgs对象池,用于写入,读取和接受套接字操作
private int m_totalBytesRead = 0; // 服务器接收的总共#个字节的计数器
private int m_numConnectedSockets = 0; // 当前连接的tcp客户端数量
private Semaphore m_maxNumberAcceptedClients = null; // 控制tcp客户端连接数量的信号量
private List<SocketAsyncEventArgs> m_connectedPool = null; // 用于socket发送数据的SocketAsyncEventArgs集合
private string m_ip = "";
private int m_port = 0;
/// <summary>
/// 创建服务端实例
/// </summary>
/// <param name="numConnections">允许连接到tcp服务器的tcp客户端数量</param>
/// <param name="bufferSize">用于socket发送和接收的缓存区大小</param>
public SocketServer(int numConnections, int bufferSize)
{
this.m_numConnections = numConnections;
this.m_bufferSize = bufferSize;
this.m_bufferManager = new BufferManager(bufferSize * numConnections, bufferSize);
this.m_readWritePool = new SocketAsyncEventArgsPool(numConnections);
this.m_connectedPool = new List<SocketAsyncEventArgs>(numConnections);
}
/// <summary>
/// 启动服务器,侦听客户端连接请求
/// </summary>
/// <param name="localEndPoint"></param>
public void Start(string ip, int port)
{
if (this.m_isRunning)
return;
if (string.IsNullOrEmpty(ip))
throw new ArgumentNullException("ip cannot be null");
if (port < 1 || port > 65535)
throw new ArgumentOutOfRangeException("port is out of range");
this.m_ip = ip;
this.m_port = port;
try
{
this.Init();
this.m_maxNumberAcceptedClients = new Semaphore(this.m_numConnections, this.m_numConnections);
// 创建 Socket 监听连接请求
this.listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress address = IPAddress.Parse(ip);
IPEndPoint endpoint = new IPEndPoint(address, port);
this.listenSocket.Bind(endpoint);
this.listenSocket.Listen(int.MaxValue); // Listen 参数表示最多可容纳的等待接受的连接数
// 接受客户端连接请求
this.StartAccept(null);
this.m_isRunning = true;
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
throw ex;
}
}
/// <summary>
/// 分配 SocketAsyncEventArg 对象池
/// </summary>
private void Init()
{
this.m_totalBytesRead = 0;
this.m_numConnectedSockets = 0;
// 分配一个大字节缓冲区,所有 I/O 操作都使用该缓冲区。
this.m_bufferManager.InitBuffer();
SocketAsyncEventArgs socketAsyncEventArgs;
for (int i = 0; i < this.m_numConnections; i++)
{
// 分配可重用的 SocketAsyncEventArgs 对象
socketAsyncEventArgs = new SocketAsyncEventArgs();
socketAsyncEventArgs.Completed += this.IO_Completed;
socketAsyncEventArgs.UserToken = new AsyncUserToken();
// 将缓冲池中的字节缓冲区分配给 SocketAsyncEventArg 对象
this.m_bufferManager.SetBuffer(socketAsyncEventArgs);
// 放入对象池
this.m_readWritePool.Push(socketAsyncEventArgs);
}
}
public void Stop()
{
if( this.m_isRunning )
{
this.m_isRunning = false;
if (this.listenSocket == null)
return;
try
{
foreach (var e in this.m_connectedPool)
{
if (this.OnConnectionBreak != null)
this.OnConnectionBreak(this, e);
AsyncUserToken token = e.UserToken as AsyncUserToken;
token.Socket.Shutdown(SocketShutdown.Both);
token.Socket.Close();
token.Socket = null;
e.Dispose();
}
this.listenSocket.LingerState = new LingerOption(true, 0);
this.listenSocket.Close();
this.listenSocket = null;
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
throw ex;
}
finally
{
this.m_connectedPool.Clear();
this.m_readWritePool.Clear();
this.m_bufferManager.FreeAllBuffer();
GC.Collect();
}
}
}
public void Restart()
{
this.Stop();
this.Start(this.m_ip, this.m_port);
}
/// <summary>
/// 开始接受来自客户端的连接请求
/// </summary>
/// <param name="acceptEventArg"></param>
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
{
if (acceptEventArg == null)
{
acceptEventArg = new SocketAsyncEventArgs();
acceptEventArg.Completed += this.AcceptEventArg_Completed;
}
else
{
acceptEventArg.AcceptSocket = null;
}
this.m_maxNumberAcceptedClients.WaitOne();
if (this.listenSocket == null)
{
return;
}
if (!this.listenSocket.AcceptAsync(acceptEventArg))
{
this.ProcessAccept(acceptEventArg);
}
}
/// <summary>
/// Socket.AcceptAsync完成回调函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
{
this.ProcessAccept(e);
}
/// <summary>
/// 接受到tcp客户端连接,进行处理
/// </summary>
/// <param name="e"></param>
private void ProcessAccept(SocketAsyncEventArgs e)
{
if (this.m_isRunning)
{
if (e.SocketError == SocketError.Success)
{
Interlocked.Increment(ref this.m_numConnectedSockets);
if (this.OnAccept != null)
this.OnAccept(this, e);
// 获取接受的客户端连接的套接字
SocketAsyncEventArgs socketAsyncEventArgs = this.m_readWritePool.Pop();
AsyncUserToken userToken = socketAsyncEventArgs.UserToken as AsyncUserToken;
userToken.Socket = e.AcceptSocket;
userToken.ConnectTime = DateTime.Now;
userToken.EndPort = e.AcceptSocket.RemoteEndPoint as IPEndPoint;
lock(this.m_lockHelper)
this.m_connectedPool.Add(socketAsyncEventArgs);
// tcp服务器开始接受tcp客户端发送的数据
if (!e.AcceptSocket.ReceiveAsync(socketAsyncEventArgs))
{
this.ProcessReceive(socketAsyncEventArgs);
}
// 接受下一个连接请求
this.StartAccept(e);
}
}
}
/// <summary>
/// socket.sendAsync和socket.recvAsync的完成回调函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void IO_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
ProcessSend(e);
break;
default:
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
}
}
/// <summary>
/// 处理接受到的tcp客户端数据
/// </summary>
/// <param name="e"></param>
private void ProcessReceive(SocketAsyncEventArgs e)
{
if (this.m_isRunning)
{
AsyncUserToken asyncUserToken = (AsyncUserToken)e.UserToken;
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
{
Interlocked.Add(ref this.m_totalBytesRead, e.BytesTransferred);
if (this.OnReceiveCompleted != null)
this.OnReceiveCompleted(this, e);
e.SetBuffer(e.Offset, this.m_bufferSize);
if (!asyncUserToken.Socket.ReceiveAsync(e))
{
this.ProcessReceive(e);
return;
}
}
else
{
this.CloseClientSocket(e);
}
}
}
/// <summary>
/// 处理tcp服务器发送的结果
/// </summary>
/// <param name="e"></param>
private void ProcessSend(SocketAsyncEventArgs e)
{
if (this.m_isRunning)
{
if (e.SocketError == SocketError.Success)
{
if (this.OnSendCompleted != null)
this.OnSendCompleted(this, e);
}
else
{
this.CloseClientSocket(e);
}
}
}
/// <summary>
/// 断开某一客户端
/// </summary>
/// <param name="e"></param>
private void CloseClientSocket(SocketAsyncEventArgs e)
{
if (this.m_isRunning)
{
if (this.OnConnectionBreak != null)
this.OnConnectionBreak(this, e);
AsyncUserToken token = e.UserToken as AsyncUserToken;
if (token != null && token.Socket != null)
{
try
{
token.Socket.Shutdown(SocketShutdown.Both);
token.Socket.Disconnect(false);
token.Socket.Close();
token.Socket = null;
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
}
finally
{
Interlocked.Decrement(ref this.m_numConnectedSockets);
this.m_readWritePool.Push(e);
this.m_maxNumberAcceptedClients.Release();
lock (this.m_lockHelper)
this.m_connectedPool.Remove(e);
}
}
}
}
/// <summary>
/// 向指定客户端发送信息
/// </summary>
/// <param name="ip"></param>
/// <param name="message"></param>
public void Send(IPEndPoint endpoint, string message)
{
byte[] buff = Encoding.UTF8.GetBytes(message);
if (buff.Length > this.m_bufferSize)
throw new ArgumentOutOfRangeException("message is out off range");
SocketAsyncEventArgs argSend = this.m_connectedPool.Find((s) =>
{
AsyncUserToken userToken = s.UserToken as AsyncUserToken;
return userToken.EndPort.ToString() == endpoint.ToString();
});
if (argSend != null)
{
AsyncUserToken userToken1 = argSend.UserToken as AsyncUserToken;
SocketAsyncEventArgs sendArg = new SocketAsyncEventArgs();
sendArg.UserToken = userToken1;
sendArg.SetBuffer(buff, 0, buff.Length);
bool willRaiseEvent = userToken1.Socket.SendAsync(sendArg);
if (!willRaiseEvent)
{
ProcessSend(sendArg);
}
}
}
/// <summary>
/// 向已连接所有客户端发送
/// </summary>
/// <param name="message"></param>
public void SendToAll(string message)
{
if (string.IsNullOrEmpty(message))
throw new ArgumentNullException("message cannot be null");
foreach (var e in this.m_connectedPool)
{
this.Send((e.UserToken as AsyncUserToken).EndPort, message);
}
}
}
}
(5)客户端操作类 SocketClient
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace JCommon.Net
{
public class SocketClient
{
public event EventHandler<SocketAsyncEventArgs> OnReceived;
public event EventHandler<SocketAsyncEventArgs> OnSendCompleted;
public event EventHandler<SocketAsyncEventArgs> OnConnectCompleted;
public event EventHandler<SocketAsyncEventArgs> OnConnectionClosed;
private readonly object lockobj = new object();
private int receiveBufferCapacity = 256;
private int sendCapacity = 1024;
private byte[] recvBuff = null; // 接收缓存数组
private byte[] sendBuff = null; // 发送缓存数组
private Socket socket = null; // 连接socket
private SocketAsyncEventArgs sendEventArg = null; // 用于发送数据的SocketAsyncEventArgs
private SocketAsyncEventArgs recvEventArg = null; // 用于接收数据的SocketAsyncEventArgs
private string ip = "";
private int port = 0;
private bool bRestart = false; // 是否开启断开重连
public SocketClient(int receiveCapacity = 1024, int sendCapacity = 256)
{
this.receiveBufferCapacity = receiveCapacity;
this.sendCapacity = sendCapacity;
// 设置用于发送数据的SocketAsyncEventArgs
sendBuff = new byte[sendCapacity];
sendEventArg = new SocketAsyncEventArgs();
sendEventArg.SetBuffer(sendBuff, 0, sendCapacity);
sendEventArg.Completed += this.IO_Completed;
sendEventArg.UserToken = new AsyncUserToken { Socket = this.socket };
// 设置用于接受数据的SocketAsyncEventArgs
recvBuff = new byte[receiveBufferCapacity];
recvEventArg = new SocketAsyncEventArgs();
recvEventArg.SetBuffer(recvBuff, 0, receiveBufferCapacity);
recvEventArg.Completed += this.IO_Completed;
recvEventArg.UserToken = new AsyncUserToken { Socket = this.socket };
}
/// <summary>
/// 断开重连
/// </summary>
public bool BRestart
{
set { this.bRestart = value; }
get { return this.bRestart; }
}
public bool Connected
{
get
{
return this.socket != null && this.socket.Connected;
}
}
public void Start(string ip, int port)
{
if (this.Connected)
return;
if (string.IsNullOrEmpty(ip))
throw new ArgumentNullException("ip cannot be null");
if (port < 1 || port > 65535)
throw new ArgumentOutOfRangeException("port is out of range");
this.ip = ip;
this.port = port;
try
{
this.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress address = IPAddress.Parse(ip);
IPEndPoint endpoint = new IPEndPoint(address, port);
// 连接tcp服务器
SocketAsyncEventArgs connectEventArg = new SocketAsyncEventArgs();
connectEventArg.Completed += ConnectEventArgs_Completed;
// 设置要连接的tcp服务器地址
connectEventArg.RemoteEndPoint = endpoint;
if (!socket.ConnectAsync(connectEventArg))
this.ProcessConnect(connectEventArg);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 关闭tcp客户端
/// </summary>
public void Stop()
{
lock (this.lockobj)
{
if (!this.Connected)
return;
try
{
// 应该在关闭socket之前先使用shutdown进行接受或者发送的禁用。
this.socket.Shutdown(SocketShutdown.Both);
this.socket.Close();
this.socket = null;
GC.Collect();
if (this.OnConnectionClosed != null)
this.OnConnectionClosed(this, null);
}
catch (Exception ex)
{
throw ex;
}
}
}
/// <summary>
/// 重启tcp客户端,重新连接tcp服务器
/// </summary>
public void Restart()
{
lock (this.lockobj)
{
this.Stop();
this.Start(ip, port);
}
}
/// <summary>
/// 异步发送
/// </summary>
/// <param name="message">要发送的数据</param>
public void Send(string message)
{
if (string.IsNullOrEmpty(message))
throw new ArgumentNullException("message cannot be null");
if (!this.Connected)
return;
byte[] buff = Encoding.UTF8.GetBytes(message);
if (buff.Length > this.sendCapacity)
throw new ArgumentNullException("message is out of range");
Array.Copy(buff, this.sendBuff, buff.Length); // or buff.CopyTo(this.sendBuff, 0);
this.sendEventArg.SetBuffer(0, buff.Length);
if (!socket.SendAsync(sendEventArg))
{
this.ProcessSend(sendEventArg);
}
}
/// <summary>
/// 大包分包发送
/// </summary>
/// <param name="sendBuff"></param>
public void SendEx(string bigmessage)
{
const int SPLITSIZE = 256;
byte[] sendBuff = Encoding.UTF8.GetBytes(bigmessage);
for (int index = 0; index < sendBuff.Length; index += SPLITSIZE)
{
if (index + SPLITSIZE <= sendBuff.Length)
{
byte[] by = new byte[SPLITSIZE];
Array.Copy(sendBuff, index, by, 0, SPLITSIZE);
this.socket.Send(by);
Array.Clear(sendBuff, index, SPLITSIZE);
}
else
{
byte[] by = new byte[SPLITSIZE];
Array.Copy(sendBuff, index, by, 0, sendBuff.Length - index);
this.socket.Send(by);
Array.Clear(sendBuff, index, sendBuff.Length - index);
}
}
}
/// <summary>
/// Socket.ConnectAsync完成回调函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ConnectEventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
this.ProcessConnect(e);
}
private void ProcessConnect(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
if (this.OnConnectCompleted != null)
{
this.OnConnectCompleted(this, e);
}
this.recvEventArg.SetBuffer(0, this.receiveBufferCapacity);
if (!this.socket.ReceiveAsync(this.recvEventArg))
{
this.ProcessReceive(this.recvEventArg);
return;
}
}
else if (e.SocketError == SocketError.ConnectionRefused || e.SocketError == SocketError.HostUnreachable || e.SocketError == SocketError.TimedOut)
{
if (this.bRestart)
{
Thread.Sleep(500);
this.Restart();
}
else
{
this.Stop();
}
}
}
/// <summary>
/// socket.sendAsync和socket.recvAsync的完成回调函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void IO_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Receive:
this.ProcessReceive(e);
break;
case SocketAsyncOperation.Send:
this.ProcessSend(e);
break;
default:
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
}
}
/// <summary>
/// 处理接收到的数据
/// </summary>
/// <param name="e"></param>
private void ProcessReceive(SocketAsyncEventArgs e)
{
if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success)
{
if (this.OnReceived != null)
{
this.OnReceived(this, e);
}
e.SetBuffer(e.Offset, this.receiveBufferCapacity);
if (!socket.ReceiveAsync(e))
{
this.ProcessReceive(e);
}
}
else
{
if (this.bRestart)
{
Thread.Sleep(500);
this.Restart();
}
else
{
this.Stop();
}
}
}
/// <summary>
/// 处理tcp客户端发送的结果
/// </summary>
/// <param name="e"></param>
private void ProcessSend(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
if (this.OnSendCompleted != null)
{
this.OnSendCompleted(this, e);
return;
}
}
else
{
if (this.bRestart)
{
Thread.Sleep(500);
this.Restart();
}
else
{
this.Stop();
}
}
}
}
}
2.使用
(1)服务器端
using JCommon.Net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace JCommon.Test
{
delegate void DelMsgShow(string str);
public partial class FrmTcpServer : Form
{
SocketServer server;
Socket sk;
private string recvBuff = string.Empty;
DelMsgShow msgShow;
void MsgShow(string str)
{
if(richTextBox1.InvokeRequired)
{
richTextBox1.Invoke(new Action<string>(MsgShow), new object[] { str });
}
else
{
richTextBox1.AppendText(str);
richTextBox1.AppendText("\r\n");
richTextBox1.ScrollToCaret();
}
}
public FrmTcpServer()
{
InitializeComponent();
}
Semaphore ss = new Semaphore(1, 1);
/// <summary>
/// 开始监听
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
string str = button1.Text;
if (str == "开始监听")
{
ServerInit();
int port = textBox1.Text.ToInt();
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port);
// server.Start(localEndPoint);
server.Start("127.0.0.1", port);
button1.Text = "停止监听";
}
else
{
server.Stop();
button1.Text = "开始监听";
}
}
/// <summary>
/// 发送
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
string strEndPort = comboBox1.Text;
string str = richTextBox2.Text;
System.Net.IPAddress IPadr = System.Net.IPAddress.Parse(strEndPort.Split(':')[0]);
IPEndPoint EndPort = new System.Net.IPEndPoint(IPadr, int.Parse(strEndPort.Split(':')[1]));
server.Send(EndPort, str);
}
private void ServerInit()
{
if (this.server == null)
{
this.server = new SocketServer(2, 1024);
this.server.OnAccept += this.server_OnAccept;
this.server.OnConnectionBreak += this.server_OnConnectionBreak;
this.server.OnReceiveCompleted += this.server_OnReceiveCompleted;
this.server.OnSendCompleted += this.server_OnSendCompleted;
}
}
private void server_OnSendCompleted(object sender, SocketAsyncEventArgs e)
{
string @string = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
Console.WriteLine(this.Name + "发送:" + @string);
msgShow("发送:" + @string);
}
private void server_OnReceiveCompleted(object sender, SocketAsyncEventArgs e)
{
string @string = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
Console.WriteLine(this.Name + "收到:" + @string);
this.recvBuff += @string.ToUpper();
msgShow("收到:" + @string);
}
private void server_OnConnectionBreak(object sender, SocketAsyncEventArgs e)
{
msgShow("连接被断开!");
JCommon.Net.AsyncUserToken userToken = e.UserToken as JCommon.Net.AsyncUserToken;
string str = userToken.EndPort.ToString();
this.comboBox1.InvokeControlAction((s) => s.Items.Remove(str));
}
private void server_OnAccept(object sender, SocketAsyncEventArgs e)
{
msgShow("有客户端接入!");
string ip = e.AcceptSocket.RemoteEndPoint.ToString();
this.comboBox1.InvokeControlAction((s) => s.Items.Add(ip));
}
private void FrmTcpServer_Load(object sender, EventArgs e)
{
textBox1.Text = "20000";
msgShow = this.MsgShow;
}
private void button3_Click(object sender, EventArgs e)
{
string str = richTextBox2.Text;
server.SendToAll(str);
}
}
}
(2)客户端
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using JCommon.Net;
namespace JCommon.Test
{
public partial class FrmTcpClient : Form
{
DelMsgShow msgShow;
void MsgShow(string str)
{
if (richTextBox1.InvokeRequired)
{
richTextBox1.Invoke(new Action<string>(MsgShow), new object[] { str });
}
else
{
richTextBox1.AppendText(str);
//richTextBox1.AppendText("\r\n");
richTextBox1.ScrollToCaret();
}
}
SocketClient client;
private string recvBuff = string.Empty;
private AutoResetEvent eventConnected = new AutoResetEvent(false);
public FrmTcpClient()
{
InitializeComponent();
}
/// <summary>
/// 连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
InitClient();
}
/// <summary>
/// 发送
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
string str = richTextBox2.Text;
if(client.Connected)
client.SendEx(str);
}
string ip;
int port;
private void InitClient()
{
if (this.client == null)
{
this.client = new SocketClient(1024);
this.client.OnConnectCompleted += this.client_OnConnectCompleted;
this.client.OnConnectionClosed += this.client_OnConnectionClosed;
this.client.OnSendCompleted += this.client_OnSendCompleted;
this.client.OnReceived += this.client_OnReceived;
this.ip = textBox1.Text;
this.port = textBox2.Text.ToInt();
}
this.client.Start(this.ip, this.port);
this.client.BRestart = true;
}
private void client_OnReceived(object sender, SocketAsyncEventArgs e)
{
string @string = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
Console.WriteLine(this.Name + "收到:" + @string);
this.recvBuff += @string.ToUpper();
msgShow(@string);
Thread.Sleep(5000);
//Thread.Sleep(50000);
}
private void client_OnSendCompleted(object sender, SocketAsyncEventArgs e)
{
string @string = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
Console.WriteLine(this.Name + "发送:" + @string);
msgShow("发送:" + @string);
}
private void client_OnConnectionClosed(object sender, SocketAsyncEventArgs e)
{
msgShow(this.Name + "连接断开");
button1.InvokeControlAction((s) => s.Enabled = true);
}
private void client_OnConnectCompleted(object sender, SocketAsyncEventArgs e)
{
AsyncUserToken asyncUserToken = e.UserToken as AsyncUserToken;
msgShow(this.Name + "客户端接入");
button3.InvokeControlAction((s) => s.Enabled = true);
button1.InvokeControlAction((s) => s.Enabled = false);
}
private void FrmTcpClient_Load(object sender, EventArgs e)
{
msgShow = this.MsgShow;
textBox1.Text = "127.0.0.1";
textBox2.Text = "20000";
}
private void button3_Click(object sender, EventArgs e)
{
if(client != null && client.Connected)
{
button3.Enabled = false;
this.client.Stop();
}
}
private void button4_Click(object sender, EventArgs e)
{
string str = richTextBox2.Text;
if (client.Connected)
client.Send(str);
}
}
}
3.演示

参考:
浙公网安备 33010602011771号