本文介绍在.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服务器的内容。