关于.NET中socket中的异步套接字的研究一
2009-08-29 20:34
405 查看
经过研究和实验,现在终于在这里可以说说socket的异步问题了。
代码采用MSDN里面官方的例子,这样的话,如果你想深入研究也有了一个通用的基础。
一直认为,其实任何技术的核心并不难,难就难在当该技术发展成熟以后为了各种需要而添加的枝枝蔓蔓,这些后期添加的东西一方面使技术的应用更加方便和稳定,另一方面,对于学习该技术的人来说,增加了不少的学习成本和障碍。我的学习技术的理念就是,将其枝枝蔓蔓的不断裁剪,一直到露出问题的最最核心,然后掌握这个核心,之后从该核心出发,顺着问题的发展思路去学习,一切就是理所当然了 。这篇文章里,我想尽量地贯穿这个思想,把我所理解的说明白。
socket构造函数如下
[align=left]
可以看到,在这里首先构造了一个IPEndPoint对象,构造该对象的目的就是要将特定的IP地址和指定的端口号捆绑到一起,一同赋给socket使用。如下:
socket.Bind(endPoint);
这一句使用socket的bind方法将特定的IP地址和指定的端口号绑定到本身。以后如果需要连接该socket就使用该IP地址和端口号。
3 开始监听
socket.Listen(32);
listen方法将socket置于监听状态。在该状态下,当有客户端连接该socket时,socket会将请求的连接按顺序排列到请求队列里面,之后按顺序通过accept方法接收连接。listen方法后的参数表示请求队列的最大数目。
同步套接字的运作过程是这样的:
1 服务器端将socket置于监听状态后,客户端发起连接请求。.NET的方法是
参数里面含有服务器端的IP地址和端口号。
2 服务器端监听到有连接的请求会接收该连接。接收的方法为
该方法不需要参数,但是返回一个socket对象,使用该对象就可以处理与连接到的客户端的一切事宜,比如接收客户端发送到的信息和发送信息至客户端等等。
3 当服务器端与客户端的连接建立之后,就可以在两方交流数据。但客户端和服务器端的程序都会等待socket的动作,也就说在在socket发送或者接收数据过程中,两方程序都会中止,一直等到发送或者接收数据完毕才会继续往下执行。
这种情况下,最明显的表现就是:如果是winForm程序,窗口会表现出死机状态,该状态到程序往下继续执行的时候才会恢复。
4 代码示例
下面看一下给出的代码示例。
首先是服务器端。
关键的地方我已经注释出来了,比较一下就明了了。
代码采用MSDN里面官方的例子,这样的话,如果你想深入研究也有了一个通用的基础。
一直认为,其实任何技术的核心并不难,难就难在当该技术发展成熟以后为了各种需要而添加的枝枝蔓蔓,这些后期添加的东西一方面使技术的应用更加方便和稳定,另一方面,对于学习该技术的人来说,增加了不少的学习成本和障碍。我的学习技术的理念就是,将其枝枝蔓蔓的不断裁剪,一直到露出问题的最最核心,然后掌握这个核心,之后从该核心出发,顺着问题的发展思路去学习,一切就是理所当然了 。这篇文章里,我想尽量地贯穿这个思想,把我所理解的说明白。
一 socket的建立
1 构造socket
不管是同步还是异步套接字,都必须首先建立起socket,这是后面连接的基础。socket构造函数如下
public Socket ( AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType )
可以看到,里面有三个构造函数,每个参数其实都是一个枚举值,详细可以查询MSDN或者vs的帮助文档。我们常用的构造函数如下:
socket = new Socket(AddressFamily.InterNetwork, , ProtocolType.Tcp);
[align=left]
第一个参数AddressFamily.InterNetwork说明我们采用IP 版本 4 的地址(现在都出版本6了);第二个参数SocketType.Stream是说建立的socket支持可靠、双向、基于连接的字节流,而不重复数据,也不保留边界,此类型的 Socket 与单个对方主机进行通信,并且在通信开始之前需要远程主机连接,Stream 使用传输控制协议 (Tcp) ProtocolType 和 InterNetworkAddressFamily。 第三个参数表名传输控制协议采用TCP。利用这三个参数就可以构造一个socket实例。[/align]
2 将socket与指定的IP地址和端口绑定
endPoint = new IPEndPoint(IPAddress.Parse(“127.0.0.1”), 65534);可以看到,在这里首先构造了一个IPEndPoint对象,构造该对象的目的就是要将特定的IP地址和指定的端口号捆绑到一起,一同赋给socket使用。如下:
socket.Bind(endPoint);
这一句使用socket的bind方法将特定的IP地址和指定的端口号绑定到本身。以后如果需要连接该socket就使用该IP地址和端口号。
3 开始监听
socket.Listen(32);listen方法将socket置于监听状态。在该状态下,当有客户端连接该socket时,socket会将请求的连接按顺序排列到请求队列里面,之后按顺序通过accept方法接收连接。listen方法后的参数表示请求队列的最大数目。
4 接收连接
当用到连接时,就涉及到同步异步的问题,下面将详细说明。二 同步与异步
要研究socket里面的异步套接字,必须从同步套接字说起。要连接至少分为两方,一方连接,另一方被连接。我们将主动发起连接的一方成为客户端,将接收连接的一方称为服务器端。无论是客户端还是服务器端,开始构造socket的过程是一致的,只是服务器端需要将socket至于监听状态,而客户端不需要。同步套接字的运作过程是这样的:
1 服务器端将socket置于监听状态后,客户端发起连接请求。.NET的方法是
public void Connect ( EndPoint remoteEP )
参数里面含有服务器端的IP地址和端口号。
2 服务器端监听到有连接的请求会接收该连接。接收的方法为
public Socket Accept ()
该方法不需要参数,但是返回一个socket对象,使用该对象就可以处理与连接到的客户端的一切事宜,比如接收客户端发送到的信息和发送信息至客户端等等。
3 当服务器端与客户端的连接建立之后,就可以在两方交流数据。但客户端和服务器端的程序都会等待socket的动作,也就说在在socket发送或者接收数据过程中,两方程序都会中止,一直等到发送或者接收数据完毕才会继续往下执行。
这种情况下,最明显的表现就是:如果是winForm程序,窗口会表现出死机状态,该状态到程序往下继续执行的时候才会恢复。
4 代码示例
下面看一下给出的代码示例。
首先是服务器端。
using System; using System.Net; using System.Net.Sockets; using System.Text; public class SynchronousSocketListener { public static string data = null; public static void StartListening() { byte[] bytes = new Byte[1024]; //首先是构造一个socket对象,构造过程就不细说了,都一样 IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()); IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000); Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); try { listener.Bind(localEndPoint); listener.Listen(10);//开始监听了 while (true) { Console.WriteLine("Waiting for a connection..."); // 接收请求连接,handler接收该连接,之后使用handler处理收发数据的问题 Socket handler = listener.Accept(); data = null; // 该循环将接收连接发送到的全部数据 while (true) { bytes = new byte[1024]; int bytesRec = handler.Receive(bytes); data += Encoding.ASCII.GetString(bytes,0,bytesRec); if (data.IndexOf("<EOF>") > -1) { break; } } // 在控制台上打印接收到的数据 Console.WriteLine( "Text received : {0}", data); // 然后下面演示服务器端发送数据至客户端,就将客户端刚发送的数据又返回给客户端了 byte[] msg = Encoding.ASCII.GetBytes(data); handler.Send(msg);//发送的方法 handler.Shutdown(SocketShutdown.Both); handler.Close(); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine("\nPress ENTER to continue..."); Console.Read(); } public static int Main(String[] args) { StartListening(); return 0; } } 这里需要注意的是,服务器端使用监听方法处于监听状态而客户端不需要监听,而下面就可以看到客户端使用connect方法连接,而服务器端用不到;再有就是服务器端会首先接收数据,之后发送数据,而客户端正好相反,次序搞错会导致程序出错。
下面是同步套接字客户端代码示例。
using System; using System.Net; using System.Net.Sockets; using System.Text; public class SynchronousSocketClient { public static void StartClient() { byte[] bytes = new byte[1024]; try { // 这里是完全一样的构造过程 IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName()) IPAddress ipAddress = ipHostInfo.AddressList[0]; IPEndPoint remoteEP = new IPEndPoint(ipAddress,11000); Socket sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp ); try { //这里使用连接方法了 sender.Connect(remoteEP); Console.WriteLine("Socket connected to {0}", sender.RemoteEndPoint.ToString()); byte[] msg = Encoding.ASCII.GetBytes("This is a test<EOF>"); // 发送数据了 int bytesSent = sender.Send(msg); // 接收数据了 int bytesRec = sender.Receive(bytes); Console.WriteLine("Echoed test = {0}", Encoding.ASCII.GetString(bytes,0,bytesRec)); sender.Shutdown(SocketShutdown.Both); sender.Close(); } catch (ArgumentNullException ane) { Console.WriteLine("ArgumentNullException : {0}",ane.ToString()); } catch (SocketException se) { Console.WriteLine("SocketException : {0}",se.ToString()); } catch (Exception e) { Console.WriteLine("Unexpected exception : {0}", e.ToString()); } } catch (Exception e) { Console.WriteLine( e.ToString()); } } public static int Main(String[] args) { StartClient(); return 0; } }
关键的地方我已经注释出来了,比较一下就明了了。
相关文章推荐
- 关于.NET中socket中的异步套接字的研究二
- .NET关于同步、异步及Socket
- .NET关于同步、异步及Socket
- .NET关于同步、异步及Socket
- 关于socket的套接字中输入输出流的理解
- 关于Java中数据报套接字DatagramSocket中connet()方法说明
- c#(Socket)异步套接字代码
- 【转】关于“不同浏览器的并发异步请求”的简单研究
- .net 3.5的Socket异步完成端口
- 关于异步socket接收数据的困惑
- .NET Socket开发之异步Socket代码祥解
- 关于Expression Tree和IL Emit的所谓的"性能差别"“.NET研究”;
- 关于套接字(socket)
- C#使用SocketAsyncEventArgs操作套接字的简单异步通讯
- [zz]关于.NET异步调用的初步总结
- .NET Socket开发之异步Socket(转)
- "现在已经正在使用此 SocketAsyncEventArgs 实例进行异步套接字操作"的处理
- 黑马程序员<.net学习---Socket套接字>
- 关于:socket阻塞、非阻塞,同步、异步、I/O模型
- 黑马程序员---.NET高级之网络套接字(Socket)编程