疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java中的Socket的用法


 

 
Java中的Socket分为普通的Socket和NioSocket。
 
普通Socket的用法
  Java中的网络通信时通过Socket实现的,Socket分为ServerSocket和Socket两大类,ServerSocket用于服务器端,可以通过accept方法监听请求,监听请求后返回Socket,Socket用于完成具体数据传输,客户端也可以使用Socket发起请求并传输数据。ServerSocket的使用可以分为三步:
 
创建ServerSocket。ServerSocket的构造方法有5个,其中最方便的是ServerSocket(int port),只需要一个port就可以了。
 
调用创建出来的ServerSocket的accept方法进行监听。accept方法是阻塞方法,也就是说调用accept方法后程序会停下来等待连接请求,在接受请求之前程序将不会继续执行,当接收到请求后accept方法返回一个Socket。
 
使用accept方法返回的Socket与客户端进行通信
 
  如下代码,我们在服务器端创建ServerSocket,并调用accept方法监听Client的请求,收到请求后返回一个Socket。
 
public class NIOServer {
 
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        try {
            //创建ServerSocketChannel,监听8080端口
            ServerSocketChannel ssc = ServerSocketChannel.open();
            ssc.socket().bind(new InetSocketAddress(8080));
            //设置为非阻塞模式
            ssc.configureBlocking(false);
            //为ssc注册选择器
            Selector selector = Selector.open();
            ssc.register(selector, SelectionKey.OP_ACCEPT);
            //创建处理器
            Handler handler = new Handler(1024);
            while(true){
                //等待请求,每次等待阻塞3s,超过3s后线程继续向下运行,如果传入0或者不传入参数则一直阻塞
                if(selector.select(3000) == 0){
                    System.out.println("等待请求超时----");
                    continue;
                }
                System.out.println("处理请求----");
                //获取处理的SelectionKey
                Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();
                while(keyIter.hasNext()){
                    SelectionKey key = keyIter.next();
                    try{
                        //接收到连接请求时
                        if(key.isAcceptable()){
                            handler.handleAccept(key);
                        }
                        //读数据
                        if(key.isReadable()){
                            handler.handleRead(key);
                        }
                    }catch(IOException ex){
                        keyIter.remove();
                        continue;
                    }
                    //处理完后,从待处理的SelectionKey迭代器中移除当前所使用的key
                    keyIter.remove();
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    private static class Handler{
        private int bufferSize = 1024;
        private String localCharset = "UTF-8";
        public Handler(int bufferSize){
            this.bufferSize = bufferSize;
        }
        public void handleAccept(SelectionKey key) throws IOException{
            SocketChannel sc = ((ServerSocketChannel) key.channel()).accept();
            sc.configureBlocking(false);
            sc.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(bufferSize));
        }
        public void handleRead(SelectionKey key) throws IOException{
            //获取Channel
            SocketChannel sc = (SocketChannel) key.channel();
            //获取buffer并重置
            ByteBuffer buffer = (ByteBuffer)key.attachment();
            buffer.clear();
            //没有读到内容则关闭
            if(sc.read(buffer) == -1)
                sc.close();
            else{
                //将buffer转换为读状态
                buffer.flip();
                //将buffer中接收到的值按localCharset格式编码后保存到receivedString
                String receivedString = Charset.forName(localCharset).newDecoder().decode(buffer).toString();
                System.out.println("received from client:" + receivedString);
                //返回数据给客户端
                String sendString = "this data is from Server";
                buffer = ByteBuffer.wrap(sendString.getBytes(localCharset));
                sc.write(buffer);
                sc.close();
            }
        }
    }
}
 
 
View Code
  客户端代码通普通Socket一样,Socket socket = new Socket("192.168.6.42",8080);表示与服务器端建立连接,从而执行服务器端的handleAccept()方法,给ServerSocketChannel注册selector以及添加SelectionKey.OP_READ参数,表示selector关心读方法。然后通过PrintWrite在客户端将内容发送给服务器端,服务器端执行handleRead方法对接收到的内容进行处理,并将结果返回给客户端,客户端通过BufferedReader接受数据,最后关闭连接。