62,620
社区成员
发帖
与我相关
我的任务
分享public class ErrorThirdNIOServer {
public static void main(String[] args) {
int serverPort = 3343;
ServerSocketChannel serverChannel = null ;
Selector selector = null ;
List<SocketChannel> clients = new ArrayList<SocketChannel>();
try {
//打开ServerSocketChannel,获得ServerSocketChannel对象。
//获得ServerSocket,并绑定监听端口
serverChannel = ServerSocketChannel.open();
ServerSocket ss = serverChannel.socket();
SocketAddress addr = new InetSocketAddress(serverPort);
ss.bind(addr);
//打开Selector,获得selector对象
selector = Selector.open();
//设置Channel对象为非阻塞。
serverChannel.configureBlocking(false);
//将通道注册到Selector中,并设置感兴趣事件
SelectionKey k = serverChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(true) {
try {
//返回你所感兴趣的事件(如连接、接受、读或写)已经准备就绪的那些通道
//回的int值表示有多少通道已经就绪
int num = selector.select();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//通过调用selector的selectedKeys()方法,访问“已选择键集(selected key set)”中的就绪通道。
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = readyKeys.iterator();
//循环遍历已选择键集中的每个键,并检测各个键所对应的通道的就绪事件
while(iterator.hasNext())
{
SelectionKey key = iterator.next();
//注意每次迭代末尾的keyIterator.remove()调用。
//Selector不会自己从已选择键集中移除SelectionKey实例。
iterator.remove();
try {
if(key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel)key.channel();
//建立与客户端连接的socket通道
SocketChannel connection = server.accept();
System.out.println("接收连接,来自:"+connection);
//设置socket连接通道为非阻塞
connection.configureBlocking(false);
//将socket通道添加到Selector中
SelectionKey key2 = connection.register
(selector, SelectionKey.OP_WRITE);
String str = "已连接到服务器!";
ByteBuffer buffer = ByteBuffer.allocate(1024);
int clientNum = 0;
if(( clientNum =clients.size())>0){
str = str+"已有"+clientNum+"个客户端连接到服务器,分别为:\r\n";
for (SocketChannel client : clients) {
str = str + client.getRemoteAddress().toString()+"\r\n";
}
}else
str = str+"没有其他客户端连接到服务器。\r\n";
buffer.put(str.getBytes("UTF-8"));
//排空buffer,将limit设置为当前位置,再将position设置为0
buffer.flip();
//将buffer添加到key2的附件中
key2.attach(buffer);
clients.add(connection);
}else
{
if(key.isReadable()) {
SocketChannel connection2 = (SocketChannel)key.channel();
// ByteBuffer buffer =(ByteBuffer) key.attachment();
ByteBuffer buffer2 = ByteBuffer.allocate(1024);
connection2.read(buffer2);
buffer2.flip();
String msg = new String(buffer2.array(),"UTF-8");
if(msg.startsWith("连接")) {
connection2.register(selector, SelectionKey.OP_WRITE );
}
}else
{
if(key.isWritable()){} {
System.out.println("服务器写");
SocketChannel connection = (SocketChannel)key.channel();
ByteBuffer buffer =(ByteBuffer) key.attachment();
if(buffer!=null) {
String msg = new String(buffer.array(),"UTF-8");
buffer.flip();
connection.write(buffer);
System.out.println(msg);
connection.register(selector, SelectionKey.OP_READ);
}
}
}
}
}catch(IOException e) {
key.cancel();
try {
clients.remove(key.channel());
key.channel().close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
}
}public class ErrorThirdNIOClient {
/***
* 客户端接收不到数据?问题可能为服务端不写,或者客户端不读?
* 但在服务器断开连接后,客户端进行一次读操作。
* @param args
*/
public static void main(String[] args) {
SocketChannel client = null ;
Selector selector = null;
InputX in = new InputX();
SocketChannel other = null;
try {
selector = Selector.open();
client = SocketChannel.open();
//注意,SocketChannel需要先设置非阻塞模式,在进行连接,不能搞错顺序
client.configureBlocking(false);
client.connect(new InetSocketAddress("localhost", 3343));
SelectionKey clientKey = client.register(selector, SelectionKey.OP_CONNECT);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while(true) {
try {
selector.select();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//通过调用selector的selectedKeys()方法,访问“已选择键集(selected key set)”中的就绪通道。
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = readyKeys.iterator();
//循环遍历已选择键集中的每个键,并检测各个键所对应的通道的就绪事件
while(iterator.hasNext()) {
SelectionKey key = iterator.next();
iterator.remove();
try {
if(key.isConnectable()) {
SocketChannel connection = (SocketChannel)key.channel();
connection.configureBlocking(false);
if(connection.isConnectionPending()) {
connection.finishConnect();
}
System.out.println("建立连接");
connection.register(selector, SelectionKey.OP_READ);
in.start();
}else {
if(key.isWritable()) {
System.out.println("客户端写");
SocketChannel connection = (SocketChannel)key.channel();
if(in.getRetu()!=null&&(!in.getRetu().equals(""))){
ByteBuffer buffer =ByteBuffer.allocate(1024);
String str = "" ;
String read = in.getRetu();
str = str+read;
buffer.put(str.getBytes("UTF-8"));
buffer.put((byte) '\r');
buffer.put((byte) '\n');
//排空buffer,将limit设置为当前位置,再将position设置为0
buffer.flip();
connection.write(buffer);
in.setRetu("");
}
} else
{
if(key.isReadable()) {
SocketChannel connection = (SocketChannel)key.channel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
//服务器关闭后,下行代码异常
connection.read(buffer);
buffer.flip();
String msg = new String(buffer.array(),"UTF-8");
System.out.println("客户端读");
System.out.println(msg);
buffer.clear();
if(msg.startsWith("连接")) {
// key.cancel();
msg = msg.substring(2);
String[] address = msg.split(":");
other = SocketChannel.open();
InetSocketAddress otherAdress =
new InetSocketAddress(address[0], Integer.parseInt(address[1]) );
other.bind(otherAdress);
other.configureBlocking(false);
other.register(selector, SelectionKey.OP_WRITE );
}else{
connection.register(selector, SelectionKey.OP_WRITE );
}
}
}
}
}catch (IOException e) {
key.cancel();
try {
key.channel().close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}
}
}
class InputX extends Thread{
private String retu ;
@Override
public void run() {
Scanner scan = new Scanner(System.in);
while(true) {
retu = scan.nextLine();
}
}
public String getRetu() {
return retu;
}
public void setRetu(String s) {
this.retu = s;
}
}