您好,欢迎访问一九零五行业门户网

C#网络编程系列文章(五)之Socket实现异步UDP服务器

本文介绍在.net中,system.net.sockets 命名空间为需要严密控制网络访问的开发人员提供了 windows sockets (winsock) 接口的托管实现。system.net 命名空间中的所有其他网络访问类都建立在该套接字socket实现之上,如tcpclient、tcplistener 和 udpclient 类封装有关创建到 internet 的 tcp 和 udp 连接的详细信息;networkstream类则提供用于网络访问的基础数据流等,常见的许多internet服务都可以见到socket的踪影,如telnet、http、email、echo等,这些服务尽管通讯协议protocol的定义不同,但是其基础的传输都是采用的socket。 其实,socket可以象流stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。
可见,在应用程序端或者服务器端创建了socket对象之后,就可以使用send/sentto方法将数据发送到连接的socket,或者使用receive/receivefrom方法接收来自连接socket的数据;
针对socket编程,.net 框架的 socket 类是 winsock32 api 提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法,大多数情况下,socket 类方法只是将数据封送到它们的本机 win32 副本中并处理任何必要的安全检查。如果你熟悉winsock api函数,那么用socket类编写网络程序会非常容易,当然,如果你不曾接触过,也不会太困难,跟随下面的解说,你会发觉使用socket类开发windows 网络应用程序原来有规可寻,它们在大多数情况下遵循大致相同的步骤。
本节介绍使用socket来实现一个高性能的异步udp服务器,实际上udp是不分客户机和服务器的,但是我们有的时候和服务器通讯就是使用udp来进行的。
socket异步udp服务器using system; using system.collections.generic; using system.linq; using system.text; using system.net; using system.net.sockets; namespace netframe.net.udp.sock.asynchronous { /// <summary> /// socket实现异步udp服务器 /// </summary> public class asyncsocketudpserver { #region fields /// <summary> /// 服务器程序允许的最大客户端连接数 /// </summary> private int _maxclient; /// <summary> /// 当前的连接的客户端数 /// </summary> //private int _clientcount; /// <summary> /// 服务器使用的同步socket /// </summary> private socket _serversock; /// <summary> /// 客户端会话列表 /// </summary> //private list<asyncudpsocketstate> _clients; private bool disposed = false; /// <summary> /// 数据接受缓冲区 /// </summary> private byte[] _recvbuffer; #endregion #region properties /// <summary> /// 服务器是否正在运行 /// </summary> public bool isrunning { get; private set; } /// <summary> /// 监听的ip地址 /// </summary> public ipaddress address { get; private set; } /// <summary> /// 监听的端口 /// </summary> public int port { get; private set; } /// <summary> /// 通信使用的编码 /// </summary> public encoding encoding { get; set; } #endregion #region 构造函数 /// <summary> /// 异步socket udp服务器 /// </summary> /// <param name="listenport">监听的端口</param> public asyncsocketudpserver(int listenport) : this(ipaddress.any, listenport,1024) { } /// <summary> /// 异步socket udp服务器 /// </summary> /// <param name="localep">监听的终结点</param> public asyncsocketudpserver(ipendpoint localep) : this(localep.address, localep.port,1024) { } /// <summary> /// 异步socket udp服务器 /// </summary> /// <param name="localipaddress">监听的ip地址</param> /// <param name="listenport">监听的端口</param> /// <param name="maxclient">最大客户端数量</param> public asyncsocketudpserver(ipaddress localipaddress, int listenport, int maxclient) { this.address = localipaddress; this.port = listenport; this.encoding = encoding.default; _maxclient = maxclient; //_clients = new list<asyncudpsocketstate>(); _serversock = new socket(localipaddress.addressfamily, sockettype.dgram, protocoltype.udp); _recvbuffer=new byte[_serversock.receivebuffersize]; } #endregion #region method /// <summary> /// 启动服务器 /// </summary> /// <returns>异步tcp服务器</returns> public void start() { if (!isrunning) { isrunning = true; _serversock.bind(new ipendpoint(this.address, this.port)); //_serversock.connect(new ipendpoint(ipaddress.any, 0)); asyncsocketudpstate so = new asyncsocketudpstate(); so.worksocket = _serversock; _serversock.beginreceivefrom(so.buffer, 0, so.buffer.length, socketflags.none, ref so.remote, new asynccallback(receivedataasync), null); //endpoint sender = new ipendpoint(ipaddress.any, 0); //_serversock.beginreceivefrom(_recvbuffer, 0, _recvbuffer.length, socketflags.none, // ref sender, new asynccallback(receivedataasync), sender); //beginreceive 和 beginreceivefrom的区别是什么 /*_serversock.beginreceive(_recvbuffer, 0, _recvbuffer.length, socketflags.none, new asynccallback(receivedataasync), null);*/ } } /// <summary> /// 停止服务器 /// </summary> public void stop() { if (isrunning) { isrunning = false; _serversock.close(); //todo 关闭对所有客户端的连接 } } /// <summary> /// 接收数据的方法 /// </summary> /// <param name="ar"></param> private void receivedataasync(iasyncresult ar) { asyncsocketudpstate so = ar.asyncstate as asyncsocketudpstate; //endpoint sender = new ipendpoint(ipaddress.any, 0); int len = -1; try { len = _serversock.endreceivefrom(ar, ref so.remote); //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); } } /// <summary> /// 发送数据 /// </summary> /// <param name="msg"></param> /// <param name="remote"></param> public void send(string msg,endpoint remote) { byte[] data = encoding.default.getbytes(msg); 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 事件 /// <summary> /// 接收到数据事件 /// </summary> public event eventhandler<asyncsocketudpeventargs> datareceived; private void raisedatareceived(asyncsocketudpstate state) { if (datareceived != null) { datareceived(this, new asyncsocketudpeventargs(state)); } } /// <summary> /// 发送数据前的事件 /// </summary> public event eventhandler<asyncsocketudpeventargs> preparesend; /// <summary> /// 触发发送数据前的事件 /// </summary> /// <param name="state"></param> private void raisepreparesend(asyncsocketudpstate state) { if (preparesend != null) { preparesend(this, new asyncsocketudpeventargs(state)); } } /// <summary> /// 数据发送完毕事件 /// </summary> public event eventhandler<asyncsocketudpeventargs> completedsend; /// <summary> /// 触发数据发送完毕的事件 /// </summary> /// <param name="state"></param> private void raisecompletedsend(asyncsocketudpstate state) { if (completedsend != null) { completedsend(this, new asyncsocketudpeventargs(state)); } } /// <summary> /// 网络错误事件 /// </summary> public event eventhandler<asyncsocketudpeventargs> neterror; /// <summary> /// 触发网络错误事件 /// </summary> /// <param name="state"></param> private void raiseneterror(asyncsocketudpstate state) { if (neterror != null) { neterror(this, new asyncsocketudpeventargs(state)); } } /// <summary> /// 异常事件 /// </summary> public event eventhandler<asyncsocketudpeventargs> otherexception; /// <summary> /// 触发异常事件 /// </summary> /// <param name="state"></param> private void raiseotherexception(asyncsocketudpstate state, string descrip) { if (otherexception != null) { otherexception(this, new asyncsocketudpeventargs(descrip, state)); } } private void raiseotherexception(asyncsocketudpstate state) { raiseotherexception(state, ""); } #endregion #region close /// <summary> /// 关闭一个与客户端之间的会话 /// </summary> /// <param name="state">需要关闭的客户端会话对象</param> public void close(asyncsocketudpstate 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 } }
会话封装类
using system; using system.collections.generic; using system.linq; using system.text; using system.net; using system.net.sockets; namespace netframe.net.udp.sock.asynchronous { public class asyncsocketudpstate { // client socket. public socket worksocket = null; // size of receive buffer. public const int buffersize = 1024; // receive buffer. public byte[] buffer = new byte[buffersize]; // received data string. public stringbuilder sb = new stringbuilder(); public endpoint remote = new ipendpoint(ipaddress.any, 0); } }
socket异步udp服务器事件参数类
using system; using system.collections.generic; using system.linq; using system.text; namespace netframe.net.udp.sock.asynchronous { /// <summary> /// socket 异步udp 事件类 /// </summary> public class asyncsocketudpeventargs : eventargs { /// <summary> /// 提示信息 /// </summary> public string _msg; /// <summary> /// 客户端状态封装类 /// </summary> public asyncsocketudpstate _state; /// <summary> /// 是否已经处理过了 /// </summary> public bool ishandled { get; set; } public asyncsocketudpeventargs(string msg) { this._msg = msg; ishandled = false; } public asyncsocketudpeventargs(asyncsocketudpstate state) { this._state = state; ishandled = false; } public asyncsocketudpeventargs(string msg, asyncsocketudpstate state) { this._msg = msg; this._state = state; ishandled = false; } } }
以上就是c#网络编程系列文章(五)之socket实现异步udp服务器的内容。
其它类似信息

推荐信息