之前一直看不懂NIO中的ServerSocketChannel和SocketChannel的区别,看了这篇博文,感觉通俗易懂,于是决定分享一下。。。。
在用nio通讯的过程我用以下情景给你模拟:
1. 学校(ServerSocketChannel)
2。 学校教务处(Selector)
3。 老师 (ServerSocket )
4。 学生 (SocketChannel)
5。 员工号/学生号(SelectionKey)
学校相当于我们的网络应用程序,一旦学校启动,学校就不停止,不断运行,直到学期结束;
要启动学校就要:
老师: 相当于服务端的Socket,一个老师对应多个学生,多个学生向老师请教,老师会一一做出回答。而学校要正常运营当然当不了老师,所以在开学之前,必须先聘请专业的老师来任教
学校教务处: 老师都有了,但是需要有部门对老师和学生做统一的管理, 如果你去一个学校找一个人,实在是找不到,你可以告诉教务处,那个人是学生还是老师,是老师的话员工编号老师姓名的多少,是学生的话学号和姓名是多少,教务处就会找到告诉你他在哪里。
ssc注册了选择器后,其下的老师ServerSocket就也入了员工册了。所以老师的编号就是skey 学生(相当于Client): 学校、老师、教务处都有了,现在就可以招生了! 如果有学生来报名:
既然有学生来报告,那有两种可能,一种是招生老师带着新生来注册的,一种是老生来问问题的。
上面的while (it.hasNext()) 体可以这样写:
补充你的补充:
ssc.register( selector, SelectionKey.OP_ACCEPT );
这个方法是把ssc注册绑定到选择器selector 这样下次你想找ssc或者判断一个对象是不是ssc就可以通过selector来查找,查找是通过判断ssc的key得到的。
至于第二个参数SelectionKey.OP_ACCEPT 你可以理解成ssc的key类型或者操作权限
如果 ssc是学校老师,那么绑定成功后 老师就拥有了OP_ACCEPT的权限或者说他的key类型是SelectionKey.OP_ACCEPT
Accept是接受的意思,这是不是很像socket编程里的 accept()方法呢? 是的,没错,我们正是通过这个参数给了老师招生和带学生来注册的权限。
而学生呢?
他拥有的权限为SelectionKey.OP_READ 表示有收发读取消息的权限,即问问题的权限,因此他不能帮别的学生注册。
所以你回到上面仔细看看while结构体里面做了判断如下:
if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {...} 很明显,拥有Accept权限的人只可能是老师,那老师有什么事会找教务处? 那肯定就是他是招生办的,招到一个学生来报名来注册了。
然后,马上给这个新连上来的客户端分配了一个key
SelectionKey newKey = sc.register( selector,
SelectionKey.OP_READ ); 看,这里只给他OP_READ,而不是Accept哦
另一个if
else
if((key.readyOps() & SelectionKey.OP_READ)== SelectionKey.OP_READ){
//很明显,这是这学生,因为所有带OP_READ的人都是前面由招生办老师带过来注册过的。