刚开始研究Java的NIO,就碰上了个问题,现在服务器端和客户段一个发一个收没有问题,但要是客户端和服务器段同时发收就有问题(我说的是双向的意思),这是为什么呢?相不明白,大家帮看看。
服务器端代码:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package niocs.newpackage.service;
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.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import javax.swing.JTextPane;
import niocs.NIOCSView;
import niocs.newpackage.service.If.IServerConnect;
/**
*
* @author Administrator
*/
public class SetUpServer implements Runnable,IServerConnect
{
private final static int MAXACCEPT = 2048;
private NIOCSView serverShow;
private ByteBuffer w_Buff = ByteBuffer.allocate(MAXACCEPT);
private final static String ENTER = "\r\n";
private int port;
private JTextPane messageContent;
private StringBuilder message = new StringBuilder();
private String fMessage = null;
public SetUpServer(NIOCSView server)
{
this.serverShow = server;
setUPServer();
}
private void setUPServer()
{
try
{
messageContent = this.serverShow.getContent();
message.append("正在初始化端口");
message.append(ENTER);
messageContent.setText(message.toString());
port = Integer.parseInt(this.serverShow.getPort().getModel().getValue().toString());
message.append("初始化端口成功!");
message.append(ENTER);
messageContent.setText(message.toString());
}
catch(ClassCastException e)
{
port = 0;
message.append("端口初始化失败!");
message.append(ENTER);
messageContent.setText(message.toString());
}
}
public void run()
{
try
{
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
Selector s = Selector.open();
ssc.socket().bind(new InetSocketAddress(port));
showMessage("系统正在建立对" + port + "端口的监听");
ssc.register(s,SelectionKey.OP_ACCEPT);
showMessage("系统已经启动!");
while(true)
{
int n = s.select();
if(n == 0)
{
continue;
}
Iterator it = s.selectedKeys().iterator();
while(it.hasNext())
{
SelectionKey key = (SelectionKey) it.next();
it.remove();
if(key.isAcceptable())
{
showMessage("有人连接到服务器.");
ServerSocketChannel server = (ServerSocketChannel) key.channel();
SocketChannel sc = server.accept();
showMessage("接受此连接请求");
sc.configureBlocking(false);
sc.register(s, SelectionKey.OP_READ);
}
if(key.isReadable())
{
SocketChannel sc = (SocketChannel)key.channel();
showMessage("正在读取数据");
if(!readData(sc))
{
key.cancel();
break;
}
sc.configureBlocking(false);
sc.register(s, SelectionKey.OP_WRITE);
}
if(key.isWritable())
{
SocketChannel sc = (SocketChannel)key.channel();
showMessage("向客户端发送数据");
fMessage = "123456";
if(!writeData(sc, fMessage))
{
key.cancel();
break;
}
sc.configureBlocking(false);
sc.register(s, SelectionKey.OP_READ);
}
}
}
}
catch(IOException e)
{
e.printStackTrace();
showMessage("读取时出错");
return;
}
}
private void showMessage(String aMessage)
{
message.append(aMessage);
message.append(ENTER);
messageContent.setText(message.toString());
}
private boolean readData(SocketChannel sc) throws IOException
{
ByteBuffer r_Buff = ByteBuffer.allocate(MAXACCEPT);
try
{
r_Buff.clear();
while(sc.read(r_Buff) > 0)
{
r_Buff.flip();
fMessage = new String(r_Buff.array()).trim();
showMessage("收的数据是:" + fMessage);
}
r_Buff = null;
return true;
}
catch(IOException e)
{
System.err.println("又报错了");
r_Buff.clear();
r_Buff.clear();
return false;
}
catch(NullPointerException e)
{
System.err.println("丫的出来空指针了");
return false;
}
}
private boolean writeData(SocketChannel sc,String message)
{
try
{
w_Buff.clear();
w_Buff.put(message.getBytes());
w_Buff.flip();
while(w_Buff.hasRemaining())
sc.write(w_Buff);
w_Buff.clear();
return true;
}
catch(IOException e)
{
System.err.println("sever已");
return false;
}
catch(NullPointerException e)
{
System.err.println("过去了都.");
return false;
}
}
public int getConnectPort()
{
return port;
}
}
这段代码实现了,接收和发送,即:服务器段受到什么就再返还给客户端。
客户端:线程1读线程
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package nioclien.backClass;
import java.io.IOException;
import java.net.ConnectException;
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;
import java.util.Set;
import javax.swing.JTextArea;
import nioclien.JSendMessage;
/**
*
* @author Administrator
*/
public class ClienReadServer implements Runnable{
private final static int MAXSIZE = 2048;
private final static String ENTER = "\r\n";
private ByteBuffer w_Buff = ByteBuffer.allocate(MAXSIZE);
private static String host;
private int port;
private JSendMessage sender;
private StringBuilder message = new StringBuilder();
private JTextArea messageReciver;
public ClienReadServer(JSendMessage sender)
{
this.sender = sender;
messageReciver = sender.getReceiveText();
initForm();
}
private void initForm()
{
try
{
port = Integer.parseInt(this.sender.getPort().getText());
host = this.sender.getIPText().getText();
}
catch(NumberFormatException e)
{
port = 0;
message.append("初始化端口失败");
message.append(ENTER);
messageReciver.setText(message.toString());
}
}
@SuppressWarnings({"static-access", "empty-statement"})
public void run()
{
if(host.trim().startsWith("."))
{
this.sender.getConnectMenuItem().setEnabled(true);
return;
}
try
{
SocketChannel channel = SocketChannel.open(new InetSocketAddress(host, port));
channel.configureBlocking(false);
Selector selector = Selector.open();
SelectionKey skey = channel.register(selector, SelectionKey.OP_READ);
showMessage("与" + host + "已经成功连接,您现在可以发送消息了.");
boolean stop = false;
int n = 0;
int read = 0;
while(!stop)
{
n = selector.select();
if(n > 0)
{
Set set = selector.selectedKeys();
Iterator it = set.iterator();
while(it.hasNext())
{
skey = (SelectionKey) it.next();
it.remove();
if(skey.isReadable())
{
SocketChannel sc = (SocketChannel) skey.channel();
readServer(sc);
}
}
}
}
}
catch(ConnectException e)
{
this.sender.getConnectMenuItem().setEnabled(true);
System.err.println("连接服务器失败.");
return;
}
catch(IOException e)
{
e.printStackTrace();
}
}
@SuppressWarnings("empty-statement")
public void readServer(SocketChannel sc) throws IOException
{
try
{
ByteBuffer r_Buff = ByteBuffer.allocate(MAXSIZE);
r_Buff.clear();
while(sc.read(r_Buff) > 0)
{
r_Buff.flip();
showMessage("收的数据是:" + new String(r_Buff.array()).trim());
}
}
catch(NullPointerException e)
{
System.err.println("时间上的问题.");
}
}
private void showMessage(String aMessage)
{
message.append(aMessage);
message.append(ENTER);
messageReciver.setText(message.toString());
}
}
客户端线程2:写线程,向服务器端发送信息。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package nioclien.backClass;
import java.io.IOException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import javax.swing.JTextArea;
import nioclien.JSendMessage;
/**
*
* @author Administrator
*/
public class ClienServer implements Runnable
{
private SocketChannel sc;
private final static int MAXSIZE = 2048;
private final static String ENTER = "\r\n";
private ByteBuffer w_Buff = ByteBuffer.allocate(MAXSIZE);
private static String host;
private int port;
private JSendMessage sender;
private StringBuilder message = new StringBuilder();
private FQueue<String> fQueue = new FQueue<String>();
public ClienServer(JSendMessage sender)
{
this.sender = sender;
initForm();
}
private void initForm()
{
try
{
port = Integer.parseInt(this.sender.getPort().getText());
host = this.sender.getIPText().getText();
}
catch(NumberFormatException e)
{
port = 0;
message.append("初始化端口失败");
message.append(ENTER);
}
}
@SuppressWarnings({"static-access", "empty-statement"})
public void run()
{
if(host.trim().startsWith("."))
{
return;
}
try
{
InetSocketAddress addr = new InetSocketAddress(host, port);
sc = SocketChannel.open();
sc.connect(addr);
while(!sc.finishConnect());//等待建立连接
while(true)
{
try
{
synchronized(fQueue)
{
if(!fQueue.isEmpty())
{
String temp = fQueue.get();
System.out.println("要发送的数据是:" + temp);
w_Buff.clear();
w_Buff.put(temp.getBytes());
w_Buff.flip();
while(w_Buff.hasRemaining())
sc.write(w_Buff);
w_Buff.clear();
}
}
}
catch(Exception e)
{
System.err.print("丫的没发送成功");
}
Thread.currentThread().sleep(1000);
}
}
catch(ConnectException e)
{
this.sender.getConnectMenuItem().setEnabled(true);
System.err.println("连接服务器失败.");
return;
}
catch(IOException e)
{
e.printStackTrace();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
public void sendMessage(String aMessage)
{
fQueue.put(aMessage);
}
private class FQueue<T>
{
private LinkedList<T> flist = new LinkedList<T>();
public void put(T o)
{
flist.addLast(o);
}
public T get()
{
return flist.removeFirst();
}
public boolean isEmpty()
{
return flist.isEmpty();
}
}
}
不知道为什么当写线程向服务器发出信息后,服务器又返还信息,客户端读线程好象并没有接收到。这是为什么呢?
- 描述: 效果页面
- 大小: 77.2 KB
分享到:
相关推荐
基于事件的 NIO 多线程服务器
### 基于事件的NIO多线程服务器解析 #### 概述 在Java的网络编程中,NIO(Non-blocking I/O)作为一种高效的数据处理模式,自JDK 1.4版本引入以来,逐渐成为了开发高性能网络应用的重要工具之一。与传统的阻塞I/O...
在Java编程中,使用非阻塞I/O(Non-blocking Input/Output,NIO)和多线程技术可以构建高效、可扩展的服务器。本篇我们将深入探讨如何利用NIO和多线程来创建一个简单的Java服务器。首先,我们需要理解NIO的基本概念...
- **NIO(Non-blocking I/O)**:NIO是Java为解决传统阻塞I/O模型中的效率问题而引入的新I/O模型。在NIO中,文件句柄可以进行非阻塞读写,即调用读写方法不会导致当前线程被挂起,而是立即返回。这使得一个线程可以...
NIO用于高性能Socket编程由来已久,网络也有较为丰富的原理和源代码。我这里主要介绍几点经验总结: ...本文粘贴多线程在NIO环境下的基本运用示例代码,同时演示了一个线程如何对多个连接进行读写的操作。
### 基于时间的NIO多...该模型不仅解决了传统多线程服务器存在的线程开销问题,还通过合理的事件机制实现了系统的可扩展性和可维护性。对于开发者来说,理解并运用这一模型可以在服务器端开发中获得更好的性能表现。
Java NIO服务器的多线程设计有助于提高服务器的并发性能,特别是在高并发场景下,可以有效地利用系统资源,避免大量线程导致的内存消耗和上下文切换开销。同时,通过选择器的使用,减少了对主线程的占用,使得服务器...
该包封装过的NIO比sun本身的更容易处理 server中只有区区几行就搞定了: //创建listener TimeHandler timer = new TimeHandler(); //获取Notifier Notifier notifier = Notifier.getNotifier(); //注册监听 notifier....
【事件回调机制】在基于事件的NIO多线程服务器设计中,事件回调机制是核心组件之一。事件回调允许服务器在特定事件发生时调用预定义的处理函数,以执行相应的业务逻辑。这种方式使得代码更加模块化,易于扩展和维护...
本篇文章将深入探讨如何使用Java NIO(非阻塞I/O)来实现阻塞多线程通信,这对于高性能服务器端应用尤其重要。我们将会分析`EchoServer.java`、`EchoClient.java`和`SocketUtils.java`这三个文件中的关键知识点。 ...
代码经过压力测试,采用反应器模式,没有第三方框架,实现功能:可以一个线程处理多个请求,也可以加上多线程。处理数据采用的多线程。实现功能:基于HTTP协议,解析请求和拼接响应,基于NIO的非阻塞,线程池,文件...
NIO_RandomAccessFile_多线程读本地CSV文件(java==> google guava包ListenableFuture) reader里有个main函数,更改文件路径后,直接运行即可
基于NIO的多线程聊天系统,代码很少,很经典,51CTO网站上的代码。有登陆和聊天界面。代码结构层次清晰,系统只有6个类。
在这个“多线程精品资源--Java NIO+多线程实现聊天室”的压缩包中,我们可以推测它包含了一套关于如何使用Java NIO和多线程技术来创建一个实时聊天应用的教程或示例代码。 首先,多线程是Java中并行处理的基础。...
Java多线程读大文件 java多线程写文件:多线程往队列中写入数据
java多线程程序设计:Java NIO+多线程实现聊天室 Java基于多线程和NIO实现聊天室 涉及到的技术点 线程池ThreadPoolExecutor 阻塞队列BlockingQueue,生产者消费者模式 Selector Channel ByteBuffer ProtoStuff 高...
使用NIO socket不需要多线程来处理多个连接的请求,效率非常高 可以作为NIO socket入门的例子,Reactor模式,重点理解key.attach, jar文件里包含了源代码 1,运行server.bat启动服务器,可以打开编辑,修改端口号 ...