学习socket nio

1:实现目标

           客户端把一个User的对象传给服务端,然后服务端把另一个User的对象传给客户端。

2:实现思路

         我们都知道,网络上传输数据都是按照字节传输的。那么我们就需要把我们所传输的对象转化成字节数据。怎么转化成字节数据呢?毫无疑问,我们会用到ByteArrayOutputStream这个类,这个类可以把流输出成字节数组。又一个问题出现了,我们怎么往ByteArrayOutputStream这个流中放数据呢?这里介绍常用的两种方法。

第一:我们可以利用序列化。也就是利用ObjectOutputStream这个类。

第二:我们可以使用DataOutputStream,这个类可以让我们按照数据类型写数据。

这里我们使用第二种方法,也就是使用DataOutputStream把对象中的字段按照类型写到

ByteArrayOutputStream流中,然后转化成字节数组。然后把字节数据放到ByteBuffer中,最后发到服务端。服务端接受到数据后,我们使用ByteArrayInputStreamDataInputStream解析字节数据,然后转化成对象。

3:代码

创建一个User类

package com.chu.test.ownnio;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class User {
	private String name;
	
	public User read(DataInputStream dis) throws IOException{
		this.name = dis.readUTF();
		return this;
	}
	public void write(DataOutputStream dos)throws IOException{
		dos.writeUTF(name);
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}


创建工具类

package com.chu.test.ownnio;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class ByteUtil {

	public static byte [] write(User user) throws IOException{
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream dos = new DataOutputStream(baos);
		user.write(dos);
		return baos.toByteArray();
	}
	
	
	public static User read(byte [] bytes) throws IOException{
		ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
		DataInputStream dis = new DataInputStream(bais);
		User u = new User();
		return u.read(dis);
	}
}


服务端代码:

package com.chu.test.ownnio;

import java.io.ByteArrayOutputStream;
import java.net.InetSocketAddress;
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.Iterator;

public class MyServer {

	public static void main(String[] args) throws Exception{
		Selector selector = Selector.open();//打开Selector
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();//打开channel
		serverSocketChannel.configureBlocking(false);//非阻塞方式
		serverSocketChannel.socket().setReuseAddress(true);//是否已本地ip发布,相当于localhost
		serverSocketChannel.socket().bind(new InetSocketAddress(8080));//端口
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); // 注册
		while(selector.select() > 0){
			Iterator<SelectionKey> it = selector.selectedKeys().iterator();
			while(it.hasNext()){
				SelectionKey key = it.next();
				ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
				SocketChannel socketChannel = ssc.accept();
				User user = receive(socketChannel);
				System.out.println("name:"+user.getName());
				
				user.setName("小强");
				send(user,socketChannel);
			}
		}
	}
	
	//接受数据
	private static User receive(SocketChannel socketChannel) throws Exception{
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		byte [] bytes = null;
		int size = 0;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		while((size = socketChannel.read(buffer))>=0){
			buffer.flip();
			bytes = new byte[size];
			buffer.get(bytes);
			baos.write(bytes);
			buffer.clear();
		}
		bytes = baos.toByteArray();
		return ByteUtil.read(bytes);
	}
	
	//发送数据
	private static void send(User user,SocketChannel socketChannel) throws Exception{
		byte [] bytes = ByteUtil.write(user);
		ByteBuffer buffer = ByteBuffer.wrap(bytes);
		socketChannel.write(buffer);
		socketChannel.socket().shutdownOutput();
	}

}


客户端代码:

package com.chu.test.nio.ownnio;

import java.io.ByteArrayOutputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class SocketClient {

	public static void main(String...args)throws Exception{
		SocketChannel socketChannel = SocketChannel.open();
		socketChannel.connect(new InetSocketAddress("localhost",8080));
		User user = new User();
		user.setName("小明");
		ByteBuffer buffer = ByteBuffer.wrap(ByteUtil.toBytes(user));
		socketChannel.write(buffer);
		socketChannel.socket().shutdownOutput();
		
		User obj = receive(socketChannel);
		System.out.println(obj.getName());
	}
	
	private static User receive(SocketChannel socketChannel)throws Exception{
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int size = 0;
		byte [] bytes = null;
		while((size = socketChannel.read(buffer))>=0){
			buffer.flip();
			bytes = new byte[size];
			buffer.get(bytes);
			baos.write(bytes);
			buffer.clear();
		}
		bytes = baos.toByteArray();
		baos.close();
		return ByteUtil.toUser(bytes);
	}
}


服务端和客户端最好放到两个eclipse中来运行,先启动服务端,然后启动客户端。就会看到控制台的输出。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值