标准的网络编程模式有一个缺点,就是如果 Socker 类的 I/O 方法不能立即处理, I/O 方法就会阻塞 (Block) 。阻塞是指程序停止执行,等待个特殊语句的完成。如当一个程序执行到 Receive 方法的时候,程序会停止执行,直到在套接字上读到的数据为止。如果远程设备不发送任何数据,程序就不能继续下去。对于单一连接的客户端 / 服务器程序这种方式也许可以正常工作,但对于必须连续处理其祂事件的程序就会引起问题。有 3 个可以避免使用阻塞网络调用的 C# 技朮:无阻塞套接字、多路传套接字和异步套接字。
1 无阻塞套接字
有一个简单的防止阻塞的方法以,就是把套接字设置成非阻塞的。如:
Socket sock=new Socket(AffressFamily.InterNetwork, SocketType.Stream,ProtocolType.Tcp);
sock.Blocking=false;
当套接字是非阻塞模式的时候,就不会一直等待一个 I/O 方法的完成,就是说,如果在规定时间内该方法不能完成,程序继续执行。比如对于 Receive 方法,如果 Blocking 设为 false,Receive 将不等待数据出现在套接字上,而是返回一个 0 值,表示在套接字上没有可用的数据。
2 多路传输套接字
另外一个解决套接字阻塞问题的方法是使用 Socket 类提供的 Select 方法,这个方法用于多路传输多个套接字实例,以便找到一个已经准备好进行读或字的套接字。格式如下:
Select(IList read,IList write ,IList error,int microseconds)
read 、 write 、 error 都是 IList 对象,这些对象包含要监视的套接字数组。 Microseconds 参数据指定 Select 方法等待事件 时要等待多长时间以微秒为单位。用法如下:
ArrayList socketList=new ArrayList(5);
socketList.Add(sock1);
socketList.Add(sock2);
Socket.Select(socketList,null,null,1000);
Byte[] buffer=new byte[1024]
for(int i=0;i<socketList.Length;i++)
{
socketList[i].Receive(buffer);
}
注意: Select 方法将监视 sock1 和 sock2 两个套接字上接收的数据。即使在两个套接字上都不有数据出理, Receive 方法也不会阻碍程序的执行。
3 异套接字的编程技朮
异理套接字编程技朮采用 AsyncCallback 委托为应用程序提供完成异理操作的方法。当某个网络功能结束时将转到 AsyncCallback 中提供的方法来结束网骆功能。这样就要以在等待网络操作完成自身的工作时,允许应用程序继续处理其祂事件。