nio udp server client Demo例子(五)

udp协议服务端单线程-多客户端交互例子

服务端

package Demo5;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;


public class NioUdpServer {
	//http://blog.csdn.net/foart/article/details/47608475
	//http://www.cnblogs.com/rainy-shurun/p/5756501.html
	//这个要多琢磨琢磨
	private int port = 8000;  
	private DatagramChannel channel;  
	private Selector selector = null;  
	
	public void initNioUdpServer() throws IOException
	{
		//创建udp连接通道
		channel = DatagramChannel.open();
		//创建通道管理器
		selector = Selector.open();
		//设置通道为非阻塞性通道(不会创建线程)
		channel.configureBlocking(false);
		//将该通道绑定对应的端口
		channel.socket().bind(new InetSocketAddress(port));
		//为通道注册通道管理器,并且注册一个可读就绪事件
		channel.register(selector, SelectionKey.OP_READ);
	}
	
	//启动轮询来接受来自客户端的数据报文
	public void listen() throws IOException 
	{
		System.out.println("new nio server start");
		while(true)
		{
			//有通道就绪时(即select()的返回值大于0时),不阻塞,否则,阻塞,不会有任何的通道加入
			selector.select();
			System.out.println("new udp server channel join");
			
			Iterator<?> it = this.selector.selectedKeys().iterator();
			while(it.hasNext())
			{
				SelectionKey key = (SelectionKey) it.next();
				it.remove();//此处负责把udp连接断掉
				clientHandler(key);	//处理来自客户端的连接(通道的各种状态)
			}
		}
	}

	private void clientHandler(SelectionKey key) throws IOException 
	{
		if(key.isReadable()){
			handlerRead(key);
		}
	}
	
	
	

	//udp的接受客户端数据和响应的过程
	private void handlerRead(SelectionKey key) throws IOException {
		
		//接受数据过程
		DatagramChannel channel =  (DatagramChannel) key.channel();
		ByteBuffer buf = ByteBuffer.allocate(1024);
		buf.clear();//固定写法
		InetSocketAddress address =(InetSocketAddress)channel.receive(buf);//接受来自客户端通道的数据
		buf.flip();//固定写法
		String content = "";
		while(buf.hasRemaining())
		{
			buf.get(new byte[buf.limit()]);
			content += new String(buf.array());
		}
		System.out.println("udp server content:"+content);
		buf.clear();
		
		//发送数据过程
		ByteBuffer buf2 = ByteBuffer.allocate(65500);
		buf2.clear();
		buf2.put("udp server put data process!!".getBytes());
		buf2.flip();
		this.channel.send(buf2,address);

	}
	
	public void close() throws IOException
	{
		this.channel.close();
		this.selector.close();
	}
	
	
	
	public static void main(String[] args) throws IOException {
		NioUdpServer server = new NioUdpServer();
		server.initNioUdpServer();
		server.listen();
		//server.close();
	}
	
}

客户端:

package Demo5;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;

public class NioUdpClient {
	private DatagramChannel channel;
	private String ip = "127.0.0.1";
	private int port = 8000;
	private Selector selector;
	
	public void initUdpClient() throws IOException
	{
		channel = DatagramChannel.open();
		selector = Selector.open();
		channel.configureBlocking(false);
		channel.connect(new InetSocketAddress(ip, port));
		//有个现象:
		//两个控制台君出现不接受数据也不发送数据,仅仅启动了两端
		// new nio client start 
		// new nio server start
		//原因猜测:注册任意事件都是与通道相关的,但是,很明显当客户端启动时,通道的各种就绪状态还没出现,所以需要手动
		//channel.write(ByteBuffer.wrap("client send msg".getBytes()));
		//来引发服务器端通道相关的就绪状态
		channel.write(ByteBuffer.wrap("client send msg".getBytes()));
		channel.register(selector, SelectionKey.OP_READ);
	}
	
	public void listen() throws IOException
	{
		System.out.println("new nio client start");
		while(true)
		{
			selector.select();
			System.out.println("new udp client channel join");
			Iterator<?> it = this.selector.selectedKeys().iterator();
			while(it.hasNext())
			{
				SelectionKey key =  (SelectionKey) it.next();
				it.remove();
				handler(key);
			}
		}
	}
	
	public void handler(SelectionKey key) throws IOException
	{
		if(key.isReadable())
		{
			handlerRead( key);
		}
	}
	
	
	public void handlerRead(SelectionKey key) throws IOException
	{
		
		
		DatagramChannel channel =  (DatagramChannel) key.channel();
		
		//接受来自服务端的数据报文
		ByteBuffer buf = ByteBuffer.allocate(65500);
		buf.clear();
		channel.receive(buf); 
		buf.flip();
		String content = "";
		while(buf.hasRemaining())
		{
			buf.get(new byte[buf.limit()]);
			content += new String(buf.array());
		}
		buf.clear();	
		System.out.println("udp client content :" + content);
		
	}
	
	public void close() throws IOException
	{
		this.channel.close();
		this.selector.close();
	}
	
	
	
	public static void main(String[] args) throws IOException {
		NioUdpClient client = new NioUdpClient();
		client.initUdpClient();
		client.listen();
		//client.close();
	}
}


测试:

eclipse下

1、启动server:

2、启动一个Client:

3、启动另外一个Client:

4、查看服务端的结果(打印了两遍msg,测试准确):

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值