最新消息:关注【太平洋学习网】微信公众号,可以获取全套资料,【全套Java基础27天】【JavaEE就业视频4个月】【Android就业视频4个月】

java Nio socket客户端和服务器端实现案例

Javaweb admin 浏览 评论

java nio socket客户端和服务器端的实现,nio socket是java.nio包下的socket,它比java.net下的socket更加高效,是一种非阻塞式的socket,采用Selector选择器形式来选择空闲的channel通道执行,Selector如我们银行叫号机器,整个项目只有一个selector叫号器,channel通道一旦建立,只要客户端不退出,就一直保持长连接的形式,如图所示。

20151214194029453.jpg

1:下面来通过案例让我们理解nio socket的使用方法,先来看看socket server服务器端的写法,代码如下。

package com.baidu;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
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.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class NioSocketServer {
	private Selector selector;
	private InetSocketAddress socketAddress;
	private Map<SocketChannel,List> channelMap;
	//构造方法
	public NioSocketServer(String address,int port){
		socketAddress = new InetSocketAddress(address, port);
		channelMap = new HashMap<SocketChannel,List>();
	}

	public static void main(String[] args) {
		Runnable server = new Runnable() {		
			@Override
			public void run() {
				try {
					new NioSocketServer("localhost", 8888).startServer();
				} catch (IOException e) {
					
					e.printStackTrace();
				}
			}
		};
		//启动线程
		new Thread(server).start();
	}
	
	//创建服务器channel通道
	protected void startServer() throws IOException {
	    //Selector对象是通过调用静态工厂方法open()来实例化
		selector = Selector.open();
		ServerSocketChannel serverChannel = ServerSocketChannel.open();
		//非阻塞
		serverChannel.configureBlocking(false);
		serverChannel.socket().bind(socketAddress);
		serverChannel.register(selector, SelectionKey.OP_ACCEPT);
		System.out.println("服务器启动了.........");
		//一直处于循环状态,便于处理客户端信息
		while(true){
			//等待客户端的事件
			selector.select();
			Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
			while(keys.hasNext()){
				SelectionKey key = keys.next();
				//防止相同的操作
				keys.remove();
				//无效则不进行下面操作
				if (!key.isValid()) {
					continue;
				}
				//如果是客户端连接操作
				if (key.isAcceptable()) {
					acceptConnection(key);
				}
				//如果是客户端来的信息,则读出来
				if (key.isReadable()) {
					readMessage(key);
				}
			}
		}
	}

	//客户端连接操作
	private void acceptConnection(SelectionKey key) throws IOException {
		ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel();
		SocketChannel channel = serverChannel.accept();
		channel.configureBlocking(false);
		Socket socket = channel.socket();
		SocketAddress remoteAddress = socket.getRemoteSocketAddress();
		System.out.println("连接的客户端ip是:"+remoteAddress);
		//开启读取数据
		channelMap.put(channel, new ArrayList<>());
		channel.register(selector, SelectionKey.OP_READ);
	}
	
	//读取客户端信息
	private void readMessage(SelectionKey key) throws IOException {
		SocketChannel channel = (SocketChannel)key.channel();
		try {
			//nio的字节缓存大小
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			int num = -1;
			num = channel.read(buffer);
			//如果数据读取完毕
			if (num == -1) {
				channelMap.remove(channel);
				Socket socket = channel.socket();
				SocketAddress remoteAddress = socket.getRemoteSocketAddress();
				System.out.println("退出的客户端ip是:"+remoteAddress);
				channel.close();
				key.cancel();
			}
			byte[] datas = new byte[num];
			System.arraycopy(buffer.array(), 0, datas, 0, num);
			String msg = new String(datas);
			System.out.println("服务端读取到的数据:"+msg);
		} catch (Exception e) {
			//客户端异常退出,则关闭通道,不影响服务端socket
			channelMap.remove(channel);
			Socket socket = channel.socket();
			SocketAddress remoteAddress = socket.getRemoteSocketAddress();
			System.out.println("退出的客户端ip是:"+remoteAddress);
			channel.close();
			key.cancel();
		}
	}
}

2:nio client客户端代码,启动连接服务器端。

package com.baidu;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Scanner;

public class NioSocketClient {
	public static void main(String[] args) throws IOException {
		InetSocketAddress socketAddress = new InetSocketAddress("localhost", 8888);
		SocketChannel client = SocketChannel.open(socketAddress);
		while(true){
		        //获取键盘录入
			Scanner scanner = new Scanner(System.in);
			System.out.println("我说:");
			String message = scanner.nextLine();
			ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
			client.write(buffer);
		}
	}

}

学会nio socket非常的重要,因为它是netty框架的基础,对于以后了解netty socket非常的有用。

来源网站:太平洋学习网,转载请注明出处:http://www.tpyyes.com/a/javaweb/2017/0810/183.html

    与本文相关的文章

    发表我的评论
    取消评论

    表情

    您的回复是我们的动力!

    • 昵称 (必填)

    网友最新评论