1:实现目标
客户端把一个User的对象传给服务端,然后服务端把另一个User的对象传给客户端。
2:实现思路
我们都知道,网络上传输数据都是按照字节传输的。那么我们就需要把我们所传输的对象转化成字节数据。怎么转化成字节数据呢?毫无疑问,我们会用到ByteArrayOutputStream这个类,这个类可以把流输出成字节数组。又一个问题出现了,我们怎么往ByteArrayOutputStream这个流中放数据呢?这里介绍常用的两种方法。
第一:我们可以利用序列化。也就是利用ObjectOutputStream这个类。
第二:我们可以使用DataOutputStream,这个类可以让我们按照数据类型写数据。
这里我们使用第二种方法,也就是使用DataOutputStream把对象中的字段按照类型写到
ByteArrayOutputStream流中,然后转化成字节数组。然后把字节数据放到ByteBuffer中,最后发到服务端。服务端接受到数据后,我们使用ByteArrayInputStream和DataInputStream解析字节数据,然后转化成对象。
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中来运行,先启动服务端,然后启动客户端。就会看到控制台的输出。