高性能异步Socket服务器(UDP)
2012-09-24 17:08
141 查看
转载自:点击打开链接
稍作修改
采用异步模式设计的UDP服务器,源码如下:
稍作修改
采用异步模式设计的UDP服务器,源码如下:
using System; using System.Net; using System.Net.Sockets; using System.Threading; using System.IO; namespace TestUDPServer { public abstract class UDPServer { // the port to listen on private int udpPort; // the UDP socket private Socket udpSocket; // the ReaderWriterLock is used solely for the purposes of shutdown (Stop()). // since there are potentially many "reader" threads in the internal .NET IOCP // thread pool, this is a cheaper synchronization primitive than using // a Mutex object. This allows many UDP socket "reads" concurrently - when // Stop() is called, it attempts to obtain a writer lock which will then // wait until all outstanding operations are completed before shutting down. // this avoids the problem of closing the socket with outstanding operations // and trying to catch the inevitable ObjectDisposedException. private ReaderWriterLock rwLock = new ReaderWriterLock(); // number of outstanding operations. This is a reference count // which we use to ensure that the threads exit cleanly. Note that // we need this because the threads will potentially still need to process // data even after the socket is closed. private int rwOperationCount = 0; // the all important shutdownFlag. This is synchronized through the ReaderWriterLock. private bool shutdownFlag = true; // these abstract methods must be implemented in a derived class to actually do // something with the packets that are sent and received. protected abstract void PacketReceived(UDPPacketBuffer buffer); protected abstract void PacketSent(UDPPacketBuffer buffer, int bytesSent); // ServiceName String ServiceName = "test"; public UDPServer(int port) { this.udpPort = port; } public void Start() { if (shutdownFlag) { // create and bind the socket IPEndPoint ipep = new IPEndPoint(IPAddress.Any, udpPort); udpSocket = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); udpSocket.Bind(ipep); // we're not shutting down, we're starting up shutdownFlag = false; // kick off an async receive. The Start() method will return, the // actual receives will occur asynchronously and will be caught in // AsyncEndRecieve(). // I experimented with posting multiple AsyncBeginReceives() here in an attempt // to "queue up" reads, however I found that it negatively impacted performance. AsyncBeginReceive(); } } protected void Stop() { if (!shutdownFlag) { // wait indefinitely for a writer lock. Once this is called, the .NET runtime // will deny any more reader locks, in effect blocking all other send/receive // threads. Once we have the lock, we set shutdownFlag to inform the other // threads that the socket is closed. rwLock.AcquireWriterLock(-1); shutdownFlag = true; udpSocket.Close(); rwLock.ReleaseWriterLock(); // wait for any pending operations to complete on other // threads before exiting. while (rwOperationCount > 0) Thread.Sleep(1); } } public bool IsRunning { // self-explanitory get { return !shutdownFlag; } } private void AsyncBeginReceive() { // this method actually kicks off the async read on the socket. // we aquire a reader lock here to ensure that no other thread // is trying to set shutdownFlag and close the socket. rwLock.AcquireReaderLock(-1); if (!shutdownFlag) { // increment the count of pending operations Interlocked.Increment(ref rwOperationCount); // allocate a packet buffer UDPPacketBuffer buf = new UDPPacketBuffer(); try { // kick off an async read udpSocket.BeginReceiveFrom( buf.Data, 0, UDPPacketBuffer.BUFFER_SIZE, SocketFlags.None, ref buf.RemoteEndPoint, new AsyncCallback(AsyncEndReceive), buf); } catch (SocketException se) { // something bad happened System.Diagnostics.EventLog.WriteEntry(ServiceName, "A SocketException occurred in UDPServer.AsyncBeginReceive():\n\n" + se.Message, System.Diagnostics.EventLogEntryType.Error); // an error occurred, therefore the operation is void. Decrement the reference count. Interlocked.Decrement(ref rwOperationCount); } } // we're done with the socket for now, release the reader lock. rwLock.ReleaseReaderLock(); } private void AsyncEndReceive(IAsyncResult iar) { // Asynchronous receive operations will complete here through the call // to AsyncBeginReceive // aquire a reader lock rwLock.AcquireReaderLock(-1); if (!shutdownFlag) { // start another receive - this keeps the server going! AsyncBeginReceive(); // get the buffer that was created in AsyncBeginReceive // this is the received data UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; try { // get the length of data actually read from the socket, store it with the // buffer buffer.DataLength = udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); buffer.StrData = System.Text.Encoding.UTF8.GetString(buffer.Data, 0, buffer.DataLength); // WritetText(string.Format("终端 IP 端口:{0}<br>接收数据:{1}<br>接收时间:{2}", buffer.RemoteEndPoint.ToString(), buffer.StrData, DateTime.Now.ToString())); // Console.WriteLine(buffer.RemoteEndPoint.ToString()); Console.WriteLine(buffer.StrData); // this operation is now complete, decrement the reference count Interlocked.Decrement(ref rwOperationCount); // we're done with the socket, release the reader lock rwLock.ReleaseReaderLock(); // call the abstract method PacketReceived(), passing the buffer that // has just been filled from the socket read. PacketReceived(buffer); } catch (SocketException se) { // something bad happened System.Diagnostics.EventLog.WriteEntry(ServiceName, "A SocketException occurred in UDPServer.AsyncEndReceive():\n\n" + se.Message, System.Diagnostics.EventLogEntryType.Error); // an error occurred, therefore the operation is void. Decrement the reference count. Interlocked.Decrement(ref rwOperationCount); // we're done with the socket for now, release the reader lock. rwLock.ReleaseReaderLock(); } } else { // nothing bad happened, but we are done with the operation // decrement the reference count and release the reader lock Interlocked.Decrement(ref rwOperationCount); rwLock.ReleaseReaderLock(); } } public void AsyncBeginSend(UDPPacketBuffer buf) { // by now you should you get the idea - no further explanation necessary rwLock.AcquireReaderLock(-1); if (!shutdownFlag) { try { Interlocked.Increment(ref rwOperationCount); udpSocket.BeginSendTo( buf.Data, 0, buf.DataLength, SocketFlags.None, buf.RemoteEndPoint, new AsyncCallback(AsyncEndSend), buf); } catch (SocketException se) { System.Diagnostics.EventLog.WriteEntry(ServiceName, "A SocketException occurred in UDPServer.AsyncBeginSend():\n\n" + se.Message, System.Diagnostics.EventLogEntryType.Error); } } rwLock.ReleaseReaderLock(); } private void AsyncEndSend(IAsyncResult iar) { // by now you should you get the idea - no further explanation necessary rwLock.AcquireReaderLock(-1); if (!shutdownFlag) { UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; try { int bytesSent = udpSocket.EndSendTo(iar); // note that call to the abstract PacketSent() method - we are passing the number // of bytes sent in a separate parameter, since we can't use buffer.DataLength which // is the number of bytes to send (or bytes received depending upon whether this // buffer was part of a send or a receive). PacketSent(buffer, bytesSent); } catch (SocketException se) { System.Diagnostics.EventLog.WriteEntry(ServiceName, "A SocketException occurred in UDPServer.AsyncEndSend():\n\n" + se.Message, System.Diagnostics.EventLogEntryType.Error); } } Interlocked.Decrement(ref rwOperationCount); rwLock.ReleaseReaderLock(); } #region 写日志记录 调试 string file = string.Empty; private string CreateFile() { string path = System.Environment.CurrentDirectory; file = string.Format("{0}/Log-{1}.html", path, DateTime.Now.ToString("yyyy-MM-dd").Split(' ')[0]); FileInfo fInfo = new FileInfo(file); if (!fInfo.Exists) { //创建文件 FileStream fs = fInfo.Create(); string temp = "<HR COLOR=red>"; byte[] data = System.Text.Encoding.Default.GetBytes(temp); fs.Write(data, 0, data.Length); fs.Flush(); fs.Close(); fs.Dispose(); } return file; } private void WritetText(string text) { CreateFile(); try { StreamWriter sw = new StreamWriter(file, true, System.Text.Encoding.Default);//File.AppendText(file); byte[] data = System.Text.Encoding.Default.GetBytes(text + " <HR Size=1><HR COLOR=red>"); sw.WriteLine(text + " <HR Size=1><HR COLOR=red>"); sw.Flush(); sw.Close(); } catch (Exception) { throw; } } #endregion } }实际使用时需继承抽象类UDPServer,并实现异步处理数据的相关方案,示例如下:
using System; namespace TestUDPServer { public class TUdpServer : UDPServer { public TUdpServer(int port) : base(port) { Console.WriteLine("Server Start...@" + port.ToString()); } protected override void PacketReceived(UDPPacketBuffer buffer) { AsyncBeginSend(buffer); } protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent) { } } }辅助类UDPPacketBuffer.cs
using System.Net; namespace TestUDPServer { // this class encapsulates a single packet that // is either sent or received by a UDP socket public class UDPPacketBuffer { // size of the buffer public const int BUFFER_SIZE = 4096; // the buffer itself public byte[] Data; // length of data to transmit public int DataLength; // the (IP)Endpoint of the remote host public EndPoint RemoteEndPoint; /// <summary> /// 显示数据 /// </summary> private string strData; public string StrData { get { return strData; } set { strData = value; } } public UDPPacketBuffer() { this.Data = new byte[BUFFER_SIZE]; // this will be filled in by the call to udpSocket.BeginReceiveFrom RemoteEndPoint = (EndPoint)new IPEndPoint(IPAddress.Any, 0); } public UDPPacketBuffer(byte[] data, EndPoint remoteEndPoint) { this.Data = data; this.DataLength = data.Length; this.RemoteEndPoint = remoteEndPoint; } } }
相关文章推荐
- 高性能异步Socket服务器(UDP)
- C#网络编程系列文章(五)之Socket实现异步UDP服务器
- Socket异步服务器,可以监控客户端的状态,功能有,文字测试,服务端向客户端传输屏幕录像(UDP传输)、监控客户端屏幕(UDP传输),抖动用户窗体、发送文件给用户、扫描客户的C盘目录。
- C#网络编程系列文章(五)之Socket实现异步UDP服务器
- .Net 异步Socket编写的UDP和TCP服务器一
- 高性能异步Socket框架
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- 使用C#.NET 实现高性能IPX/SPX SOCKET服务器 附源码
- C#网络编程系列文章(五)之Socket实现异步UDPserver
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- SOCKET Communication writen in C# (7) Socket 高性能异步操作 模式
- 转载:异步IO、APC、IO完成端口、线程池与高性能服务器之一 异步IO
- 高性能的 socket 通讯服务器(完成端口模型--IOCP)
- 高性能UDP服务器的开发
- socket tcp/ip UDP, 多线程 同步 异步 研究
- 使用C#task和异步socket实现多线程服务器
- (转自:Never-say-Never)Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)
- 异步Socket服务器与客户端
- 高性能的socket通讯服务器(完成端口模型--IOCP)
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)