.NET Socket开发之异步Socket代码祥解
2009-05-31 23:17
411 查看
在基于.NET的网络服务端的开发中,我们用到和听到的最多的恐怕就是异步Socket了。异步Socket的性能比同步高出很多,但是编写代码比较复杂。因此异步Socket也是网络上讨论比较多的话题。
今天,我们就来讨论一下如何用异步Socket开发网络应用。在此之前我们先讨论两个问题。
一、异步Socket是如何工作的:
那异步Socket是如何工作的呢?我以接收一条消息来说明这个问题。首先,程序向系统投递一个接收数据的请求,并为其指定一个数据缓冲区和回调函数,回调函数用来指示当数据到达后将如何处理,然后我们的程序继续执行下去,当有数据到达的时候,系统将数据读入缓冲区,并执行回调函数,处理这条消息。我们并不需要关心这条消息何时到达。
二、什么情况下我们用异步Socket:
有些人认为,异步Socket的性能比同步Socket的性能高很多,应该在各种环境下都用异步Socket,其实不然。在某些环境下面。异步反到比同步的性能低,那么在哪些情况下会这样呢?
1、客户端Socket。
2、服务端连接数比较少。
3、连接数很多,但都是短连接。
在这些环境下,我们用同步Socket不但可以简化代码,而且性能并不会比异步Socket低。但在服务端连接比较多而且是长连接的情况下,我们就要使用异步Socket。
现在我们来看看如何用异步Socket编程。
首先,我们要建立一个Socket用来监听:
Socket _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEP = new IPEndPoint(_address, _port);
_listener.Bind(localEP);
_listener.Listen(100);
然后创建一个线程来处理客户端连接请求: Thread _acceptWorkThread = new Thread(AcceptWorkThread);
_acceptWorkThread.Start();
private void AcceptWorkThread()
...{
while (_isListener)
...{
UserInfo info = new UserInfo();//这个UserInfo是用来保存客户信息的。
info.socket = socket;
Socket socket = _listener.Accept();
//这里进行其它处理。
socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, ReceiveCallBack, info);//这里向系统投递一个接收信息的请求,并为其指定ReceiveCallBack做为回调函数
}
} 我们再来看看回调函数的定义:
private void ReceiveCallBack(IAsyncResult ar)
...{
UserInfo info = (UserInfo)ar.AsyncState;
Socket handler = info.socket;
int readCount = 0;
try
...{
readCount = handler.EndReceive(ar);//调用这个函数来结束本次接收并返回接收到的数据长度。
}
catch (SocketException)//出现Socket异常就关闭连接
...{
CloseSocket(info);//这个函数用来关闭客户端连接
return;
}
catch
...{
}
if (readCount > 0)
...{
byte[] buffer = new byte[readCount];
Buffer.BlockCopy(info.Buffer, 0, buffer, 0, readCount);
Analyzer(info, buffer);//这个函数用来处理接收到的信息。
try
...{
handler.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), info);//向系统投递下一个接收请求
}
catch (SocketException) //出现Socket异常就关闭连接
...{
CloseSocket(info);
}
catch
...{
}
}
else //如果接收到0字节的数据说明客户端关闭了Socket,那我们也要关闭Socket
...{
CloseSocket(info);
}
}接下来我们看看如何发送数据给客户端:
public void Send(Socket socket, byte message)
...{
try
...{
info.socket.BeginSend(message, 0, _byte.Length, SocketFlags.None, new AsyncCallback(SendCallBack), info);//这里向系统投递一个发送数据的请求,并指定一个回调函数。
}
catch (SocketException ex)
...{
CloseSocket(info);
}
catch
...{
}
}定义发送回调函数:
private void SendCallBack(IAsyncResult ar)
...{
UserInfo info = (UserInfo)ar.AsyncState;
try
...{
info.socket.EndSend(ar);//调用这个函数来结束本次发送。
}
catch
...{
}
}
好了,整个监听、接收、发送的过程就完成了,很简单吧。现在需要说明的是,我在这里接收客户端连接的Accept是用的同步的,我个人认为在这里用同步的会比用异步好一些。因为这样代码简单而且没有性能上的损失。
今天我就写到这里了!下次我们再继续。
今天,我们就来讨论一下如何用异步Socket开发网络应用。在此之前我们先讨论两个问题。
一、异步Socket是如何工作的:
那异步Socket是如何工作的呢?我以接收一条消息来说明这个问题。首先,程序向系统投递一个接收数据的请求,并为其指定一个数据缓冲区和回调函数,回调函数用来指示当数据到达后将如何处理,然后我们的程序继续执行下去,当有数据到达的时候,系统将数据读入缓冲区,并执行回调函数,处理这条消息。我们并不需要关心这条消息何时到达。
二、什么情况下我们用异步Socket:
有些人认为,异步Socket的性能比同步Socket的性能高很多,应该在各种环境下都用异步Socket,其实不然。在某些环境下面。异步反到比同步的性能低,那么在哪些情况下会这样呢?
1、客户端Socket。
2、服务端连接数比较少。
3、连接数很多,但都是短连接。
在这些环境下,我们用同步Socket不但可以简化代码,而且性能并不会比异步Socket低。但在服务端连接比较多而且是长连接的情况下,我们就要使用异步Socket。
现在我们来看看如何用异步Socket编程。
首先,我们要建立一个Socket用来监听:
Socket _listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint localEP = new IPEndPoint(_address, _port);
_listener.Bind(localEP);
_listener.Listen(100);
然后创建一个线程来处理客户端连接请求: Thread _acceptWorkThread = new Thread(AcceptWorkThread);
_acceptWorkThread.Start();
private void AcceptWorkThread()
...{
while (_isListener)
...{
UserInfo info = new UserInfo();//这个UserInfo是用来保存客户信息的。
info.socket = socket;
Socket socket = _listener.Accept();
//这里进行其它处理。
socket.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, ReceiveCallBack, info);//这里向系统投递一个接收信息的请求,并为其指定ReceiveCallBack做为回调函数
}
} 我们再来看看回调函数的定义:
private void ReceiveCallBack(IAsyncResult ar)
...{
UserInfo info = (UserInfo)ar.AsyncState;
Socket handler = info.socket;
int readCount = 0;
try
...{
readCount = handler.EndReceive(ar);//调用这个函数来结束本次接收并返回接收到的数据长度。
}
catch (SocketException)//出现Socket异常就关闭连接
...{
CloseSocket(info);//这个函数用来关闭客户端连接
return;
}
catch
...{
}
if (readCount > 0)
...{
byte[] buffer = new byte[readCount];
Buffer.BlockCopy(info.Buffer, 0, buffer, 0, readCount);
Analyzer(info, buffer);//这个函数用来处理接收到的信息。
try
...{
handler.BeginReceive(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallBack), info);//向系统投递下一个接收请求
}
catch (SocketException) //出现Socket异常就关闭连接
...{
CloseSocket(info);
}
catch
...{
}
}
else //如果接收到0字节的数据说明客户端关闭了Socket,那我们也要关闭Socket
...{
CloseSocket(info);
}
}接下来我们看看如何发送数据给客户端:
public void Send(Socket socket, byte message)
...{
try
...{
info.socket.BeginSend(message, 0, _byte.Length, SocketFlags.None, new AsyncCallback(SendCallBack), info);//这里向系统投递一个发送数据的请求,并指定一个回调函数。
}
catch (SocketException ex)
...{
CloseSocket(info);
}
catch
...{
}
}定义发送回调函数:
private void SendCallBack(IAsyncResult ar)
...{
UserInfo info = (UserInfo)ar.AsyncState;
try
...{
info.socket.EndSend(ar);//调用这个函数来结束本次发送。
}
catch
...{
}
}
好了,整个监听、接收、发送的过程就完成了,很简单吧。现在需要说明的是,我在这里接收客户端连接的Accept是用的同步的,我个人认为在这里用同步的会比用异步好一些。因为这样代码简单而且没有性能上的损失。
今天我就写到这里了!下次我们再继续。
相关文章推荐
- 你应该知道的.net平台下socket异步通讯(代码实例)
- .NET Socket开发之异步Socket
- .NET Socket开发之异步Socket(转)
- .NET Socket开发之异步Socket
- .NET Socket开发之异步Socket
- RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->新增“行政区域管理”,同时大批量树采用异步加载
- .Net语言 APP开发平台——Smobiler学习日志:Poplist控件在APP中的应用场景以及代码
- 一个基于jQuery ajax和.net httphandler 的超轻异步框架,千行代码完成。
- ACE Proactor机制下的异步SOCKET开发
- .net 3.5平台上的Socket开发
- .NET开发 程序员必备工具 -- FxCop:监视代码工具
- J2ME 拼图游戏 快速开发 全过程 之代码祥解(1 )——程序入口与控制器开发
- J2ME 拼图游戏 快速开发 全过程 之代码祥解(6 )——欢迎界面、游戏结束后的等待界面与增加用户名字界面
- 关闭 晓K的专栏 我的学习历程 目录视图摘要视图订阅 赠书 | 异步2周年,技术图书免费选 每周荐书:渗透测试、K8s、架构(评论送书) 项目管理+代码托管+文档协作,开发更
- VC++利用socket开发udp数据接收程序的步骤(异步方式)
- .net知识系列之九:分布式开发(xml webservice介绍和服务器开发,异步调用)
- 关于.NET中socket中的异步套接字的研究二
- 《.NET 4.0网络开发入门之旅》4:与Socket的第一次“约会”
- Flash使用xmlsocket与.net服务端异步通信
- 用VS2008开发.net 2.0 Web程序用时用到UpdatePanel 控件时要在Web.Config添加以下代码