C#实现的异步套接字封装了server与client.docx
《C#实现的异步套接字封装了server与client.docx》由会员分享,可在线阅读,更多相关《C#实现的异步套接字封装了server与client.docx(15页珍藏版)》请在冰豆网上搜索。
![C#实现的异步套接字封装了server与client.docx](https://file1.bdocx.com/fileroot1/2023-2/8/71e83fac-90f5-41eb-bcba-95740a4ddfbd/71e83fac-90f5-41eb-bcba-95740a4ddfbd1.gif)
C#实现的异步套接字封装了server与client
C#实现的异步套接字,封装了server与client
最近半年以来都在从事suse10下的C++开发,开发工具也从豪门visualstudio10降到了代码查看工具sourceinsight。
不过不得不说sourceinsight阅读代码的效率绝对超过visualstudio,虽然visualstudio也能设置哪些功能,但真心没sourceinsight顺手。
不过悲剧的就是写代码的支持比文本好不了多少,调试的话,只能上传到suse10服务器上去然后慢慢的gdb调试了,最头大的就是那个makefile的编写,实在让人累。
还是怀念windows下那种豪华的日子。
废话不多说了,我写这篇文章不是为了诉苦的,只是为了继续写网络这边的。
以前写过windows下的C++的网络编程的一些日子,虽然也被喷过不少,不过今天我还是要来写网络编程,只是语言更换为豪华的C#。
之所以说C#豪华,相信同时使用C#与C++的人能体会到。
framework实在是太强大了,基本我就关注一点点东西就行了,很多类似工具的东西都是可以直接拿过来使用,而且最为关键的是我们在天朝,不用花钱用企业版,小小鄙视下自己,不过我还是会继续支持山寨盗版,谁让我是屌丝呢。
今天文章中写的是异步,纯粹的异步,当然很多人看来很简单了,而且里面很多东西值得商榷,不过说真的,我真心感谢C#的线程池,不然我还要自己去写个threadpool。
而且我没办法保证我写的没问题。
直接上代码了,不讲思路了,没时间,最近太忙,已经几天没睡好了。
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Net.Sockets;
usingSystem.Net;
usingSystem.Threading;
namespacePPT.Comm
{
///
///接收数据流
///
///异步套接字
///接收到的数据流
publicdelegatevoidAsyncDataAcceptedEventHandler(AsyncSocketm_pSocket,byte[]m_pDatagram);
///
///发送完毕
///
///异步套接字
///发送结果
publicdelegatevoidAsyncDataSendedEventHandler(AsyncSocketm_pSocket,boolm_pIsSuccess);
///
///接收连接委托
///
///异步套接字
publicdelegatevoidAsyncSocketAcceptEventHandler(AsyncSocketm_pSocket);
///
///关闭连接委托
///
///异步套接字
publicdelegatevoidAsyncSocketClosedEventHandler(AsyncSocketm_pSocket);
///
///Stateobjectforreceivingdatafromremotedevice.
///
classStateObject
{
//Clientsocket.
publicSocketworkSocket=null;
//Sizeofreceivebuffer.
publicconstintBufferSize=1024*256;
//Receivebuffer.
publicbyte[]buffer=newbyte[BufferSize];
//Receiveddatastring.
publicStringBuildersb=newStringBuilder();
}
///
///异步SOCKET
///
publicclassAsyncSocket
{
#region私有字段成员
privateSocketm_socket=null;//socket
stringm_id="";//socket唯一标识,GUID
privatereadonlyboolm_isSerevr;//服务器标志位
privateintm_iBackBag;
privatestringm_ipAddress;
privateintm_port;
privateAsyncDataAcceptedEventHandlerm_onAsyncDataAcceptedEvent=null;//接收数据流
privateAsyncDataSendedEventHandlerm_onAsyncDataSendedEvent=null;//发送结束
privateAsyncSocketAcceptEventHandlerm_onAsyncSocketAcceptEvent=null;//接收连接
privateAsyncSocketClosedEventHandlerm_onAsyncSocketClosedEvent=null;//关闭连接
#endregion
#region公共属性成员
///
///获取SOCKET标志位
///
publicstringID
{
get
{
returnm_id;
}
}
///
///设置或获取机器标志位
///
publicstringMachineKey
{
set;
get;
}
///
///获取、设置连接对象
///
publicSocketLinkObject
{
get
{
returnm_socket;
}
set
{
m_socket=value;
}
}
///
///设置或获取线程退出标识
///
publicboolIsExit{set;get;}
#endregion
#region公共事件成员
///
///连接关闭事件
///
publiceventAsyncSocketClosedEventHandlerAsyncSocketClosedEvent
{
add
{
m_onAsyncSocketClosedEvent+=value;
}
remove
{
m_onAsyncSocketClosedEvent-=value;
}
}
///
///连接接收事件
///
publiceventAsyncSocketAcceptEventHandlerAsyncSocketAcceptEvent
{
add
{
m_onAsyncSocketAcceptEvent+=value;
}
remove
{
m_onAsyncSocketAcceptEvent-=value;
}
}
///
///数据接收完成事件
///
publiceventAsyncDataAcceptedEventHandlerAsyncDataAcceptedEvent
{
add
{
this.m_onAsyncDataAcceptedEvent+=value;
}
remove
{
this.m_onAsyncDataAcceptedEvent-=value;
}
}
///
///数据发送完成事件
///
publiceventAsyncDataSendedEventHandlerAsyncDataSendedEvent
{
add
{
m_onAsyncDataSendedEvent+=value;
}
remove
{
m_onAsyncDataSendedEvent-=value;
}
}
#endregion
#region构造函数成员
///
///构造函数
///
///主机地址,可为机器名或者IP
///主机端口
///是否作为服务器,默认为false
///支持多少个客户端
publicAsyncSocket(stringm_pHostAddrss,intm_pHostPort,boolm_pIsAsServer=false,intm_pIBackBag=10)
{
m_isSerevr=m_pIsAsServer;
m_iBackBag=m_pIBackBag;
m_ipAddress=m_pHostAddrss;
m_port=m_pHostPort;
m_id=Guid.NewGuid().ToString();
}
///
///构造函数,用于服务器构造与客户端的异步socket
///
///客户端socket
privateAsyncSocket(SocketlinkObject)
{
m_socket=linkObject;
m_id=Guid.NewGuid().ToString();
}
#endregion
#region公共方法
///
///打开通道
///
publicvoidAsyncOpen()
{
if(m_isSerevr)
{
IPAddressip=Dns.GetHostAddresses(m_ipAddress)[0];
IPEndPointipe=newIPEndPoint(ip,m_port);
m_socket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
m_socket.Bind(ipe);
m_socket.Listen(m_iBackBag);
m_socket.BeginAccept(newAsyncCallback(AcceptCallBack),null);//异步
}
else
{
IPAddressip=Dns.GetHostAddresses(m_ipAddress)[0];
IPEndPointipe=newIPEndPoint(ip,m_port);
m_socket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
m_socket.Connect(ipe);
}
}
///
///发送二进制数据
///
///
publicvoidAsyncSend(byte[]SendData)
{
m_socket.BeginSend(SendData,0,SendData.Length,0,newAsyncCallback(SendCallBack),m_socket);
}
///
///关闭通道
///
publicvoidAsyncClose()
{
if(!
m_isSerevr)
{
m_socket.Shutdown(SocketShutdown.Both);//关闭接收发送流
m_socket.BeginDisconnect(false,CloseCallBack,m_socket);//开始尝试断开
}
else
{
m_socket.Shutdown(SocketShutdown.Both);//关闭接收发送流
Thread.Sleep(200);//等待现有任务处理完成
m_socket.Dispose();//释放所有本地资源
}
}
///
///开始接受数据,连接建立之后,调用此方法
///
publicvoidBeginAcceptData()
{
//开始接收数据
StateObjectstate=newStateObject();
state.workSocket=m_socket;
m_socket.BeginReceive(state.buffer,0,StateObject.BufferSize,0,newAsyncCallback(ReceiveCallback),state);
}
#endregion
#region私有方法成员
#endregion
#region回调函数成员
///
///接受客户端连接处理
///
///
privatevoidAcceptCallBack(IAsyncResultar)
{
Sockethandler=m_socket.EndAccept(ar);
AsyncSocketNewSocket=newAsyncSocket(handler);
//激发事件,异步触发
if(m_onAsyncSocketAcceptEvent!
=null)
foreach(AsyncSocketAcceptEventHandleriteminm_onAsyncSocketAcceptEvent.GetInvocationList())
item.BeginInvoke(NewSocket,null,null);
//继续投递监听请求
m_socket.BeginAccept(newAsyncCallback(AcceptCallBack),null);
}
///
///接受字节流处理
///
///
privatevoidReceiveCallback(IAsyncResultar)
{
try
{
StateObjectstate=ar.AsyncStateasStateObject;
//读取数据
intbytesRead=m_socket.EndReceive(ar);
if(bytesRead>0)
{
byte[]_Readbyte=newbyte[bytesRead];
Array.Copy(state.buffer,0,_Readbyte,0,bytesRead);
//接收完成,激发事件
if(m_onAsyncDataAcceptedEvent!
=null)
foreach(AsyncDataAcceptedEventHandleriteminm_onAsyncDataAcceptedEvent.GetInvocationList())
item.BeginInvoke(this,_Readbyte,null,null);
state=newStateObject();//继续投递接收委托
state.workSocket=m_socket;
m_socket.BeginReceive(state.buffer,0,StateObject.BufferSize,0,newAsyncCallback(ReceiveCallback),state);
}
}
catch(SocketException)
{
if(m_onAsyncSocketClosedEvent!
=null)
foreach(AsyncSocketClosedEventHandleriteminm_onAsyncSocketClosedEvent.GetInvocationList())
item.BeginInvoke(this,null,null);
}
}
///
///发送结束处理
///
///
privatevoidSendCallBack(IAsyncResultar)
{
try
{
m_socket.EndSend(ar);
if(m_onAsyncDataSendedEvent!
=null)
foreach(AsyncDataSendedEventHandleriteminm_onAsyncDataSendedEvent.GetInvocationList())
item.BeginInvoke(this,true,null,null);
}
catch(SocketException)
{
if(m_onAsyncDataSendedEvent!
=null)
foreach(AsyncDataSendedEventHandleriteminm_onAsyncDataSendedEvent.GetInvocationList())
item.BeginInvoke(this,false,null,null);
if(m_onAsyncSocketClosedEvent!
=null)
foreach(AsyncSocketClosedEventHandleriteminm_onAsyncSocketClosedEvent.GetInvocationList())
item.BeginInvoke(this,null,null);
}
}
///
///关闭后处理
///
///
privatevoidCloseCallBack(IAsyncResultar)
{
try
{
m_socket.EndDisconnect(ar);
m_socket.Dispose();
if(m_onAsyncDataSendedEvent!
=null)
foreach(AsyncSocketClosedEventHandleriteminm_onAsyncSocketClosedEvent.GetInvocationList())
item.BeginInvoke(this,null,null);
}
catch(SocketException)
{
if(m_onAsyncSocketClosedEvent!
=null)
foreach(AsyncSocketClosedEventHandleriteminm_onAsyncSocketClosedEvent.GetInvocationList())
item.BeginInvoke(this,null,null);
}
}
#endregion
}
}
代码注释还是蛮详细的,相信你看了也没什么不懂的地方。
唯一让我不爽的是我异步事件不得不
foreach(AsyncSocketAcceptEventHandleriteminm_onAsyncSocketAcceptEvent.GetInvocationList())
item.BeginInvoke(NewSocket,null,null);
这样的写法,很蛋疼。
也试验了
ActionasyncAction=()=>m_onAsyncSocketAcceptEvent();
asyncAction.BeginInvoke(null,null);
但郁闷的发现其实action虽然异步了,但那些事件还是顺序触发的,根本不是并发触发。
无奈还是写那个蛋疼的foreach语句。
顺便提到一句那个foreach中类型写全了,别用var,因为var会自动推断为Delegate。
当然你自己再转换下也行,如果你喜欢的话。