Udp 异步通信(三)
转自:https://blog.csdn.net/zhujunxxxxx/article/details/44258719
1)服务端
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; namespace UdpSocketServer { public class UdpServerAsync { #region Fields private int _maxClient; private Socket _serverSock; private List<EndPoint> _clients; private bool disposed = false; private byte[] _recvBuffer; #endregion #region Properties public bool IsRunning { get; private set; } public IPAddress Address { get; private set; } public int Port { get; private set; } public Encoding Encoding { get; set; } #endregion #region 构造函数 public UdpServerAsync(int listenPort) : this(IPAddress.Any, listenPort, 1024) { } public UdpServerAsync(IPEndPoint localEP) : this(localEP.Address, localEP.Port, 1024) { } public UdpServerAsync(IPAddress localIPAddress, int listenPort, int maxClient) { this.Address = localIPAddress; this.Port = listenPort; this.Encoding = Encoding.Default; _maxClient = maxClient; _serverSock = new Socket(localIPAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp); _recvBuffer = new byte[_serverSock.ReceiveBufferSize]; } #endregion #region Method public void Start() { if (!IsRunning) { IsRunning = true; _serverSock.Bind(new IPEndPoint(this.Address, this.Port)); //_serverSock.Connect(new IPEndPoint(IPAddress.Any, 0)); SocketState so = new SocketState(); so.buffer = new byte[_serverSock.ReceiveBufferSize]; so.remote = new IPEndPoint(Address, Port); _serverSock.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None, ref so.remote, new AsyncCallback(ReceiveDataAsync), so); } } public void Stop() { if (IsRunning) { IsRunning = false; _serverSock.Close(); } } private void ReceiveDataAsync(IAsyncResult ar) { SocketState so = ar.AsyncState as SocketState; int len = -1; try { len = _serverSock.EndReceiveFrom(ar, ref so.remote); so.recvSize = len; //len = _serverSock.EndReceiveFrom(ar, ref sender); //EndReceiveFrom 和 EndReceive区别 //len = _serverSock.EndReceive(ar); //TODO 处理数据 //触发数据收到事件 RaiseDataReceived(so); } catch (Exception) { //TODO 处理异常 RaiseOtherException(so); } finally { if (IsRunning && _serverSock != null) _serverSock.BeginReceiveFrom(so.buffer, 0, so.buffer.Length, SocketFlags.None, ref so.remote, new AsyncCallback(ReceiveDataAsync), so); } } public void Send(byte[] data, EndPoint remote) { try { RaisePrepareSend(null); _serverSock.BeginSendTo(data, 0, data.Length, SocketFlags.None, remote, new AsyncCallback(SendDataEnd), _serverSock); } catch (Exception) { //TODO 异常处理 RaiseOtherException(null); } } private void SendDataEnd(IAsyncResult ar) { ((Socket)ar.AsyncState).EndSendTo(ar); RaiseCompletedSend(null); } #endregion #region 事件 public event EventHandler<UDPMessage> DataReceived; private void RaiseDataReceived(SocketState state) { if (DataReceived != null) { DataReceived(this, new UDPMessage(state)); } } /// <summary> /// 发送数据前的事件 /// </summary> public event EventHandler<UDPMessage> PrepareSend; /// <summary> /// 触发发送数据前的事件 /// </summary> /// <param name="state"></param> private void RaisePrepareSend(SocketState state) { if (PrepareSend != null) { PrepareSend(this, new UDPMessage(state)); } } /// <summary> /// 数据发送完毕事件 /// </summary> public event EventHandler<UDPMessage> CompletedSend; /// <summary> /// 触发数据发送完毕的事件 /// </summary> /// <param name="state"></param> private void RaiseCompletedSend(SocketState state) { if (CompletedSend != null) { CompletedSend(this, new UDPMessage(state)); } } /// <summary> /// 网络错误事件 /// </summary> public event EventHandler<UDPMessage> NetError; /// <summary> /// 触发网络错误事件 /// </summary> /// <param name="state"></param> private void RaiseNetError(SocketState state) { if (NetError != null) { NetError(this, new UDPMessage(state)); } } /// <summary> /// 异常事件 /// </summary> public event EventHandler<UDPMessage> OtherException; /// <summary> /// 触发异常事件 /// </summary> /// <param name="state"></param> private void RaiseOtherException(SocketState state, string descrip) { if (OtherException != null) { OtherException(this, new UDPMessage(descrip, state)); } } private void RaiseOtherException(SocketState state) { RaiseOtherException(state, ""); } #endregion #region Close /// <summary> /// 关闭一个与客户端之间的会话 /// </summary> /// <param name="state">需要关闭的客户端会话对象</param> public void Close(SocketState state) { if (state != null) { //_clients.Remove(state); //_clientCount--; //TODO 触发关闭事件 } } /// <summary> /// 关闭所有的客户端会话,与所有的客户端连接会断开 /// </summary> public void CloseAllClient() { //foreach (AsyncUDPSocketState client in _clients) //{ // Close(client); //} //_clientCount = 0; //_clients.Clear(); } #endregion #region 释放 /// <summary> /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Releases unmanaged and - optionally - managed resources /// </summary> /// <param name="disposing"><c>true</c> to release /// both managed and unmanaged resources; <c>false</c> /// to release only unmanaged resources.</param> protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { try { Stop(); if (_serverSock != null) { _serverSock = null; } } catch (SocketException) { //TODO RaiseOtherException(null); } } disposed = true; } } #endregion } }
2)客户端
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; namespace UdpSocketClient { public class UDPClientAsync { #region 字段 public Socket udpClient; public EndPoint endPoint; private SocketState state; #endregion #region 属性 public IPAddress Address { get; private set; } public int Port { get; private set; } #endregion #region 构造函数 public UDPClientAsync(IPAddress ipAddress,int port) { this.Address = ipAddress; this.Port = port; endPoint = new IPEndPoint(Address, Port); udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); } public UDPClientAsync(IPEndPoint ipEndPoint) :this(ipEndPoint.Address,ipEndPoint.Port) { } #endregion #region Method public void Send(byte[] bytes) { udpClient.BeginSendTo(bytes, 0, bytes.Length, SocketFlags.None, endPoint, iAsyncResult=> { udpClient.EndSendTo(iAsyncResult); RaiseDataSend(); }, null); } public void Receive() { state = new UdpSocketClient.SocketState(); state.buffer = new byte[udpClient.ReceiveBufferSize]; state.remote = new IPEndPoint(Address, Port); udpClient.BeginReceiveFrom(state.buffer, 0, state.buffer.Length, SocketFlags.None, ref state.remote, new AsyncCallback(DataReceivedCallBack), null); } private void DataReceivedCallBack(IAsyncResult iAsyncResult) { int len = -1; try { len = udpClient.EndReceiveFrom(iAsyncResult, ref state.remote); state.recvSize = len; RaiseDataReceived(state); } catch(Exception ex) { RaiseErrorException(ex.Message); } //if (udpClient != null) //{ // udpClient.BeginReceiveFrom(state.buffer, 0, state.buffer.Length, SocketFlags.None, ref state.remote, // new AsyncCallback(DataReceivedCallBack), null); //} } public void Close() { udpClient.Shutdown(SocketShutdown.Both); udpClient.Close(); GC.Collect(); } #endregion #region 事件 public event EventHandler<UDPMessage> DataReceived; private void RaiseDataReceived(SocketState state) { if(DataReceived!=null) { DataReceived(this, new UdpSocketClient.UDPMessage(state)); } } public event EventHandler<UDPMessage> DataSend; private void RaiseDataSend() { if(DataSend!=null) { DataSend(this, null); } } public event EventHandler<UDPMessage> ErrorException; private void RaiseErrorException(string msg) { if(ErrorException!=null) { ErrorException(this, new UdpSocketClient.UDPMessage(msg)); } } #endregion } }
3)消息类
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text; namespace UdpSocketServer { public class SocketState { public Socket workSocket = null; public byte[] buffer; public int recvSize; public EndPoint remote; public string Diagram { get { byte[] data = new byte[recvSize]; Array.ConstrainedCopy(buffer, 0, data, 0, recvSize); //_datagram = Encoding.Default.GetString(data); return Encoding.Default.GetString(data); } } } }
4)服务端信息类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UdpSocketClient
{
public class UDPMessage : EventArgs
{
/// <summary>
/// 提示信息
/// </summary>
public string _msg;
{
public class UDPMessage : EventArgs
{
/// <summary>
/// 提示信息
/// </summary>
public string _msg;
/// <summary>
/// 客户端状态封装类
/// </summary>
public SocketState _state;
/// 客户端状态封装类
/// </summary>
public SocketState _state;
/// <summary>
/// 是否已经处理过了
/// </summary>
public bool IsHandled { get; set; }
/// 是否已经处理过了
/// </summary>
public bool IsHandled { get; set; }
public UDPMessage(string msg)
{
this._msg = msg;
IsHandled = false;
}
public UDPMessage(SocketState state)
{
this._state = state;
IsHandled = false;
}
public UDPMessage(string msg, SocketState state)
{
this._msg = msg;
this._state = state;
IsHandled = false;
}
}
}
{
this._msg = msg;
IsHandled = false;
}
public UDPMessage(SocketState state)
{
this._state = state;
IsHandled = false;
}
public UDPMessage(string msg, SocketState state)
{
this._msg = msg;
this._state = state;
IsHandled = false;
}
}
}