在网络通讯的编程中我们经常使用到Socket, 这种情况下我们往往需要长期的监听某个端口, 以获得相应的Socket, 然后再利用它进行相关操作. 但是这样的话, 主线程就会被阻塞.无法对其他时间做出相应. 其实在.Net的Socket类中提供了对异步操作的支持. 下面将介绍其基本原理, 以及利用它做的一个P2P的实现.
背景知识:
你需要了解有关Socket的基本知识, 以及Delegate的异步调用操作.
在这个例子中, 我们实现了一个利用非阻塞(non-blocking)的Socket进行局域网通讯的P2P应用. 每个客户拥有一个Grid(类似于一个二维数组), 当它启动Grid设置服务的时候,一旦别的客户与它相连就可以查询并修改某个网格中的数值.(比如查询 grid[1][2]的值).
运行步骤:
1. 启动服务 在某个客户端输入 start 400 (400是端口号, 你可以任意指定)
2. 连接其他Peer 在另一个客户端中输入 connect 202.119.9.12 400 (202.119.9.12 400是某个开启服务的客户端的IP地址)
3. 输入 get 1 1 表示你想获得grid[1][1]这个网格中的数值. 默认情况下得到0
4. 输入 set 1 1 5 表示你想设置grid[1][1]这个网格中的数值为5 .
5. 再次输入 get 1 1 查询到结果为已修改的5
6. 输入shutdown 关闭与刚才与当前的Peer的连接. 你可以再次连接别的Peer
运行示意图.
在通常的应用中Server往往需要长期处于监听状态, 以等待Client的连接. 下面是一个典型的应用.
看到那个do {} while( true )了吗?
只要if( listener.Pending() )的条件不被满足,这个过程中,主线程就处于被阻塞的状态, 当然很不利于与用户的交互(还以为死机了呢).
于是就希望有一种非阻塞的机制来实现网络间的通讯. 如果你熟悉java的话, 你可能用过java1.4中的nio (new io). 其中的select机制就是用于解决此问题的. 其实在.net中也有类似于它的一个机制, 而且通过事件触发的异步操作, 使得它更方便被使用, 也更容易被理解.
首先来看看服务器是如何监听客户端的连接的.
注意最后一行代码, BeginAccept 为以后client真正接入的时候设置好了回调函数, 也就是说一旦server发现有client连接它, server端的 OnConnectRequest方法就将被调用.
那么OnConnectRequest方法中又将做一些什么事呢?
这里利用连接获得的socket, 向client发回了连接成功的信息.
随后又跳回了BeginAccept的状态, 继续监听, 也就是允许有多用户连接.
再来看看连接的那方.
BeginConnect为连接成功设置了回调方法OnConnect, 一旦与服务器连接成功就会执行该方法. 来看看OnConnect具体做了什么
它在检测确实连接成功后, 又使用BeginReceive注册了接受数据的回调函数.
它在检测确实连接成功后又使用注册了接受数据的回调函数
我们可以发现在整个过程中就是通过事件的不断触发, 然后在预先设置好的回调函数中做相应的处理工作,比如发送接受数据.下面这幅图将让你对这个事件触发的过程有一个形象的认识.
配合附带的源代码, 相信可以让你对此过程有更加深入的了解.
至于本文有关P2P的示例, 其实还很不完善. 只是为每个Peer同时提供了充当服务器和客户端的功能. 当然在这个基础上你可以很方便的做出你想要的效果.
在网络通讯的编程中我们经常使用到Socket, 这种情况下我们往往需要长期的监听某个端口, 以获得相应的Socket, 然后再利用它进行相关操作. 但是这样的话, 主线程就会被阻塞.无法对其他时间做出相应. 其实在.Net的Socket类中提供了对异步操作的支持. 下面将介绍其基本原理, 以及利用它做的一个P2P的实现.
背景知识:
你需要了解有关Socket的基本知识, 以及Delegate的异步调用操作.
在这个例子中, 我们实现了一个利用非阻塞(non-blocking)的Socket进行局域网通讯的P2P应用. 每个客户拥有一个Grid(类似于一个二维数组), 当它启动Grid设置服务的时候,一旦别的客户与它相连就可以查询并修改某个网格中的数值.(比如查询 grid[1][2]的值).
运行步骤:
1. 启动服务 在某个客户端输入 start 400 (400是端口号, 你可以任意指定)
2. 连接其他Peer 在另一个客户端中输入 connect 202.119.9.12 400 (202.119.9.12 400是某个开启服务的客户端的IP地址)
3. 输入 get 1 1 表示你想获得grid[1][1]这个网格中的数值. 默认情况下得到0
4. 输入 set 1 1 5 表示你想设置grid[1][1]这个网格中的数值为5 .
5. 再次输入 get 1 1 查询到结果为已修改的5
6. 输入shutdown 关闭与刚才与当前的Peer的连接. 你可以再次连接别的Peer
运行示意图.
在通常的应用中Server往往需要长期处于监听状态, 以等待Client的连接. 下面是一个典型的应用.
看到那个do {} while( true )了吗?
只要if( listener.Pending() )的条件不被满足,这个过程中,主线程就处于被阻塞的状态, 当然很不利于与用户的交互(还以为死机了呢).
于是就希望有一种非阻塞的机制来实现网络间的通讯. 如果你熟悉java的话, 你可能用过java1.4中的nio (new io). 其中的select机制就是用于解决此问题的. 其实在.net中也有类似于它的一个机制, 而且通过事件触发的异步操作, 使得它更方便被使用, 也更容易被理解.
首先来看看服务器是如何监听客户端的连接的.
注意最后一行代码, BeginAccept 为以后client真正接入的时候设置好了回调函数, 也就是说一旦server发现有client连接它, server端的 OnConnectRequest方法就将被调用.
那么OnConnectRequest方法中又将做一些什么事呢?
这里利用连接获得的socket, 向client发回了连接成功的信息.
随后又跳回了BeginAccept的状态, 继续监听, 也就是允许有多用户连接.
再来看看连接的那方.
BeginConnect为连接成功设置了回调方法OnConnect, 一旦与服务器连接成功就会执行该方法. 来看看OnConnect具体做了什么
它在检测确实连接成功后, 又使用BeginReceive注册了接受数据的回调函数.
它在检测确实连接成功后又使用注册了接受数据的回调函数
我们可以发现在整个过程中就是通过事件的不断触发, 然后在预先设置好的回调函数中做相应的处理工作,比如发送接受数据.下面这幅图将让你对这个事件触发的过程有一个形象的认识.
配合附带的源代码, 相信可以让你对此过程有更加深入的了解.
至于本文有关P2P的示例, 其实还很不完善. 只是为每个Peer同时提供了充当服务器和客户端的功能. 当然在这个基础上你可以很方便的做出你想要的效果.