socket nio 多线程接收客户端信息

转载 2015年07月07日 12:53:14

在连接数很大的情况下,使用Selector能减少并发线程数,减少上下文切换的消耗,非阻塞IO使得具备流程的读写。


package main;
 
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class Server {
    private final int PORT = 1234;
    private ExecutorService pool;
    private ServerSocketChannel ssc;
    private Selector selector;
    private static Charset charset = Charset.forName("utf-8");
    private int n;
     
    public static void main(String[] args) throws IOException{
        Server server = new Server();
        server.doService();
    }
     
    public Server() throws IOException{
        pool = Executors.newFixedThreadPool(5);
         
        ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);
        ServerSocket ss = ssc.socket();
        ss.bind(new InetSocketAddress(PORT));
        selector = Selector.open();
        ssc.register(selector,SelectionKey.OP_ACCEPT);
        System.out.println("Server started...");
    }
     
    public void doService(){
        while(true){
            try{
                n = selector.select();
            }catch (IOException e) {
                throw new RuntimeException("Selector.select()异常!");
            }
            if(n==0)
                continue;
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> iter = keys.iterator();
            while(iter.hasNext()){
                SelectionKey key = iter.next();
                iter.remove();
                if(key.isAcceptable()){
                    SocketChannel sc = null;
                    try{
                        sc = ((ServerSocketChannel)key.channel()).accept();
                        sc.configureBlocking(false);
                        System.out.println("客户端:"+sc.socket().getInetAddress().getHostAddress()+" 已连接");
                        SelectionKey k = sc.register(selector, SelectionKey.OP_READ);
                        ByteBuffer buf = ByteBuffer.allocate(1024);
                        k.attach(buf);
                    }catch (Exception e) {
                        try{
                            sc.close();
                        }catch (Exception ex) {
                        }
                    }
                }
                else if(key.isReadable()){
                    key.interestOps(key.interestOps()&(~SelectionKey.OP_READ));
                    pool.execute(new Worker(key));
                }
            }
        }
    }
     
    public static class Worker implements Runnable{
        private SelectionKey key;
        public Worker(SelectionKey key){
            this.key = key;
        }
         
        @Override
        public void run() {
            SocketChannel sc = (SocketChannel)key.channel();
            ByteBuffer buf = (ByteBuffer)key.attachment();
            buf.clear();
            int len = 0;
            try{
                while((len=sc.read(buf))>0){//非阻塞,立刻读取缓冲区可用字节
                    buf.flip();
                    System.out.println("客户端:"+charset.decode(buf).toString());
                    buf.clear();
                }
                if(len==-1){
                    System.out.println("客户端断开。。。");
                    sc.close();
                }
                //没有可用字节,继续监听OP_READ
                key.interestOps(key.interestOps()|SelectionKey.OP_READ);
                key.selector().wakeup();
            }catch (Exception e) {
                try {
                    sc.close();
                } catch (IOException e1) {
                }
            }
        }
    }
}


Java Socket(六) 使用多线程实现多客户端的通信

问题一个服务端可以跟多个客户端通讯基本步骤1.服务器端创建ServerSocket方法,循环调用accept()方法等待客户端连接2.客户端创建socket和服务的请求连接3.服务端接受客户端的请求,...
  • u013007900
  • u013007900
  • 2015年12月27日 11:02
  • 11824

Java nio Socket非阻塞模式

NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有 事件发生时,他会通知我们,传回一组Select...
  • itachi85
  • itachi85
  • 2012年11月18日 16:51
  • 3951

C# 实现的多线程异步Socket数据包接收qi框架

几天前在博问中看到一个C# Socket问题,就想到笔者2004年做的一个省级交通流量接收服务器项目,当时的基本求如下: 接收自动观测设备通过无线网卡、Internet和Socket上报的交通量...
  • woddle
  • woddle
  • 2014年09月28日 10:37
  • 975

java nio socket实现多线程多用户通信

本程序在客户端异常退出后有时会在服务器端有死循环,望读者知悉 server端代码: package com.lifeix.d20131009; import java.io.IOException...
  • jiangfullll
  • jiangfullll
  • 2013年10月11日 20:56
  • 2647

NIO应用实现多客户端与服务端通信

服务端程序:package com.bh.server; import java.io.IOException; import java.net.InetSocketAddress; import...
  • cuiyaoqiang
  • cuiyaoqiang
  • 2016年05月10日 10:25
  • 1103

java socket多线程 接收xml

java socket多线程 接收xml2009-08-21 17:25这段时间做了个项目,不过觉得一直是我在写,我们总监再改。。看样子自己的代码能力太差了。而且乱七八糟的啦。。现将代码分享一下吧 :...
  • zhaome
  • zhaome
  • 2009年12月30日 09:37
  • 2973

Socket+NIO实现客户端与服务器的通信的Demo

之前在写一个即使通讯软件的时候使用了阻塞式IO来完成通讯,在服务器对于没一个客户端的链接,服务器都要启动一个线程来维持客户端的阻塞。虽然我使用了线程池来优化线程的开销,但难免还是有性能上的瓶颈...
  • canot
  • canot
  • 2016年05月11日 10:58
  • 4482

java socket & Nio 之 利用线程池改进

前面描述了BIO中采用1对1模式的服务器架构,发展它不适合高并发,高性能的服务器业务需求,那么接下来我们采用一个改进版来改进一下这个结构,这个结构主要是改进服务器端的程序。改进的措施如下: 1.在服...
  • qq513036862
  • qq513036862
  • 2016年12月12日 17:06
  • 1155

nio中客户端发送一次数据,服务端通过多次readable事件才能完整读取

最近在开发一个c/s项目,主要功能是:客户端负责采集数据发送给服务端入库。 客户端与服务端交互大致过程如下: 客户端发送一次数据,服务端read一次数据并解析入库。 先描述下问题,后面会贴出较为详...
  • t8500071
  • t8500071
  • 2013年01月21日 14:31
  • 1504

JavaSocket聊天器<三>多线程客户端向服务端发送信息

题接上文:在现在,我们实现了客户端向服务端的信息发送,此时的发送,仅仅是单个的客户端,能否让多个客户端给服务端发信息,答案是可以的,必须要运用多线程的知识。 客户端代码: /** * 实现多线程...
  • tianwei11
  • tianwei11
  • 2015年01月06日 21:30
  • 1720
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:socket nio 多线程接收客户端信息
举报原因:
原因补充:

(最多只允许输入30个字)