java网络编程的演进总结

这是一个从”单挑“,到”我要打十个“,再到”万人敌“的故事。

基于TCP/IP网络,对基础网络操作的封装。

三个核心类:InetAddress,Socket,ServerSocket

客户端(InetAddress + Socket)
1:socket通过IP和PORT,寻找服务器并建立连接
2:getInputStream() 获取服务器返回的流数据:
3:getOutputStream 向服务器写入要传递的数据流
4:最后关闭流合连接。

服务器端:ServerSocket

1:绑定端口进行监听
2:服务器进入无限循环,开始accpt()等待,直到获取Socket,此Socket绑定客户端的Ip和端口
3:getInputStream() 获取服务器返回的流数据:
4:getOutputStream 向服务器写入要传递的数据流
5:继续循环Accept,即:重复步骤2 

--------------------------------------------------------------------------------
在客户端和服务器过程中
因为服务器端的主线程中accept是阻塞的,所以,普通的实现,只能是一对一的交互。

为了能够使服务器同时响应更多的客户端,服务器端引入多线程技术。

1:server.accept()得到的Socket
2:新创建线程t1,并将1中产生的Socket传递给t1,t1.start()开始执行
3:重复1~2,这样就同时会有多个线程在服务器端运行。 

--------------------------------------------------------------------------------

一对多的问题解决之后,就是性能问题。
性能问题集中在两个地方

1:IO --由BIO升级为NIO
2:网络连接 -- 添加事件模型通过Selector获取和分发网络操作事件。
3:业务逻辑(根据实际业务逻辑,不是必然的)


阻塞IO:简单,但是Socket的accept和read()方法都是阻塞的,即使没有数据也会阻塞。并且每个客户端都需要一个线程,当服务器有大量客户端时,不考虑处理器和内存的时候,线程数就会成为瓶颈。


NIO:可以使一个或者几个线程,处理大量的客户端。

1:打开ServerSocketChannel,打开Selector,serverSocketChannel绑定端口,设置为非阻塞模式,注册OP_ACCEPT事件。
        ServerSocketChannel server = ServerSocketChannel.open();   
        Selector sel = Selector.open();  
        server.socket().bind(new InetSocketAddress(port)); //绑定端口  
        server.configureBlocking(false);//非阻塞模型   
        server.register(sel, SelectionKey.OP_ACCEPT); //注册ACCEPT操作
2:Server开始监听,OP_ACCEPT事件(此监听同时监听了可读,可写等事件)。
     try {
            for (;;) {
                selector.select();
                Iterator iter = selector.selectedKeys().iterator();
                while (iter.hasNext()) {
                    SelectionKey key = (SelectionKey) iter.next();
                    iter.remove();
                    process(key);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
3:监听到OP_ACCEPT事件,获取SocketChannel,注册OP_READ事件。
     ServerSocketChannel server = (ServerSocketChannel) key.channel();
            SocketChannel channel = server.accept();
            //设置非阻塞模式
            channel.configureBlocking(false);
             channel.register(selector, SelectionKey.OP_READ);
4:监听到OP_READ,读取数据,同时注册OP_WRITE事件。
     SocketChannel channel = (SocketChannel) key.channel();
            int count = channel.read(clientBuffer);
            if (count > 0) {
                clientBuffer.flip();
                CharBuffer charBuffer = decoder.decode(clientBuffer);
                name = charBuffer.toString();
                System.out.println(name);
                 SelectionKey sKey = channel.register(selector,
                        SelectionKey.OP_WRITE);

                sKey.attach(name);
            } else {
                channel.close();
            }

            clientBuffer.clear();
5:监听到OP_WRITE,写入数据。      SocketChannel channel = (SocketChannel) key.channel();
            String name = (String) key.attachment();

            ByteBuffer block = encoder.encode(CharBuffer
                    .wrap("Hello !" + name));
            channel.write(block);
            channel.close();//通道关闭
--------------------------------------------------------------------------------------------------
总之,我们从“单挑”升级为“我要打十个”,一直走到了“万人敌”。IO,线程,内存,CPU。

注:源码摘自某文章(纯为了说明一些问题),细节处可能需要斟酌

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值