本人新手,请教关于nio数据接受不全的问题
本人写了一个C/S模式的通讯程序。但是考虑想测试大数据时是否能通。但是出现了问题。数据接受不完全。
下面是代码,求帮忙!
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
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.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server2 {
private final int PORT = 12347;
private ExecutorService pool;
private ServerSocketChannel ssc;
private Selector selector;
private static Charset charset = Charset.forName("utf-8");
private int n;
int clientCount;
public static void main(String[] args) throws IOException {
Server server = new Server();
server.doService();
}
public Server2() throws IOException {
// pool = Executors.newFixedThreadPool(5);
pool = Executors.newCachedThreadPool();
ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ServerSocket ss = ssc.socket();
ss.bind(new InetSocketAddress(PORT));
selector = Selector.open();
ssc.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Server started...");
}
public void doService() {
while (true) {
try {
n = selector.select();
} catch (IOException e) {
throw new RuntimeException("Selector.select()异常!");
}
if (n == 0)
continue;
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iter = keys.iterator();
while (iter.hasNext()) {
SelectionKey key = iter.next();
iter.remove();
if (key.isAcceptable()) {
SocketChannel sc = null;
try {
sc = ((ServerSocketChannel) key.channel()).accept();
clientCount++;
sc.configureBlocking(false);
System.out.println("第" + clientCount + "个客户端:"
+ sc.socket().getInetAddress().getHostAddress()
+ "已连接");
SelectionKey k = sc.register(selector,
SelectionKey.OP_READ);
ByteBuffer buf = ByteBuffer.allocate(102400);
k.attach(buf);
} catch (Exception e) {
try {
sc.close();
} catch (Exception ex) {
}
}
} else if (key.isReadable()) {
key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));
pool.execute(new Worker(key));
}else if(key.isWritable()) {
SocketChannel chan = (SocketChannel) key.channel();
String date="";
int i=0;
while(i<25000)
{
date=date+String.valueOf(i)+ ":This is just a reply to confirm my UDP communication\n";
i++;
}
System.out.println(date);
ByteBuffer buf = ByteBuffer.wrap(date.getBytes());
buf.position(buf.limit());
buf.flip();
while(buf.hasRemaining()) {
try {
chan.write(buf);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
buf.clear();
if(key.isValid()) {
key.interestOps(SelectionKey.OP_READ);
}
}
}
}
}
public static class Worker implements Runnable {
private SelectionKey key;
public Worker(SelectionKey key) {
this.key = key;
}
@Override
public void run() {
long starttime = System.currentTimeMillis();
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buf = (ByteBuffer) key.attachment();
buf.clear();
int len = 0;
try {
while ((len = sc.read(buf)) > 0) {// 非阻塞,立刻读取缓冲区可用字节
buf.flip();
System.out.println("客户端:"
+ charset.decode(buf).toString());
buf.clear();
}
if (len == -1) {
System.out.println("客户端断开!");
sc.close();
}
// 没有可用字节,继续监听OP_READ
key.interestOps(SelectionKey.OP_WRITE);
key.selector().wakeup();
} catch (Exception e) {
try {
sc.close();
} catch (IOException e1) {
}
}
long endtime = System.currentTimeMillis();
System.out.println("处理耗时:"
+ (endtime - starttime));
}
}
}
之后是client端的代码(也是nio);
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class NioClient {
//管道管理器
private Selector selector;
public NioClient init(String serverIp, int port) throws IOException{
//获取socket通道
SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
//获得通道管理器
selector=Selector.open();
//客户端连接服务器,需要调用channel.finishConnect();才能实际完成连接。
channel.connect(new InetSocketAddress(serverIp, port));
//为该通道注册SelectionKey.OP_CONNECT事件
channel.register(selector, SelectionKey.OP_CONNECT);
return this;
}
public void listen() throws IOException{
System.out.println("客户端启动");
//轮询访问selector
while(true){
//选择注册过的io操作的事件(第一次为SelectionKey.OP_CONNECT)
selector.select();
Iterator<SelectionKey> ite = selector.selectedKeys().iterator();
while(ite.hasNext()){
SelectionKey key = ite.next();
//删除已选的key,防止重复处理
ite.remove();
if(key.isConnectable()){
SocketChannel channel=(SocketChannel)key.channel();
//如果正在连接,则完成连接
if(channel.isConnectionPending()){
channel.finishConnect();
}
channel.configureBlocking(false);
//向服务器发送消息
String date="";
int i=0;
while(i<25000){
date=date+String.valueOf(i)+":this is a test to confirm my UDP communication\n";
i++;
}
channel.write(ByteBuffer.wrap(date.getBytes()));
//连接成功后,注册接收服务器消息的事件
channel.register(selector, SelectionKey.OP_READ);
System.out.println("客户端连接成功");
}else if(key.isReadable()){ //有可读数据事件。
SocketChannel channel = (SocketChannel)key.channel();
ByteBuffer buffer = ByteBuffer.allocate(10240);
channel.read(buffer);
byte[] data = buffer.array();
String message = new String(data);
System.out.println("recevie message from server:, size:" + buffer.position() + " msg: " + message);
// ByteBuffer outbuffer = ByteBuffer.wrap(("client.".concat(msg)).getBytes());
// channel.write(outbuffer);
}
}
}
}
public static void main(String[] args) throws IOException {
new NioClient().init("127.0.0.1", 12345).listen();
}
}