非阻塞通信

最近看孙老师的《Java网络编程精解》,读到非阻塞通信!感觉框架的重要性!服务器端和客户端的开发可以有框架遵循!开始写歌简单的,然后逐渐添加功能!

package nonblock;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.net.*;
import java.util.*;

public class MyServer {

private ServerSocketChannel ssc ;
private Selector selector ;
private int port = 8000;
private Charset charset = Charset.forName("GBK");
public static int num = 1;

public MyServer() throws IOException{
selector = Selector.open();
ssc = ServerSocketChannel.open();
ssc.socket().setReuseAddress(true);
ssc.configureBlocking(false);
ssc.socket().bind(new InetSocketAddress(port));
System.out.println("Serve 启动了!");
}

public void server() throws IOException{
ssc.register(selector, SelectionKey.OP_ACCEPT);
while(selector.select()>0){
Set keySet = selector.selectedKeys();
Iterator iter = keySet.iterator();
while(iter.hasNext()){
SelectionKey key = (SelectionKey)iter.next();
//一定要remove,否则会一直存在
iter.remove();
if(key.isAcceptable()){
ServerSocketChannel s = (ServerSocketChannel)key.channel();
SocketChannel sc = (SocketChannel)s.accept();
System.out.println("服务器端接收到连接...");
System.out.println("客户端信息"+sc.socket().getLocalAddress()+":"+sc.socket().getPort());
sc.configureBlocking(false);
ByteBuffer buffer = ByteBuffer.allocate(1024);
sc.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE, buffer);
System.out.println("服务器完成注册...");
}
if(key.isReadable()){
// receive(key);
// System.out.println("服务器端可以读取信息...");
}
if(key.isWritable()){
// System.out.println("服务器端可以写入信息...");
}
}
}
}

public void receive(SelectionKey key) throws IOException {
ByteBuffer buffer = (ByteBuffer)key.attachment();
SocketChannel socketChannel = (SocketChannel)key.channel();
ByteBuffer readBuffer = ByteBuffer.allocate(2);
socketChannel.read(readBuffer);
readBuffer.flip();

System.out.println((num++)+"From client:"+charset.decode(readBuffer).toString());
buffer.limit(readBuffer.capacity());
buffer.put(readBuffer);

}

public void send(SelectionKey key) throws IOException {
ByteBuffer buffer = (ByteBuffer)key.attachment();
String str = charset.decode(buffer).toString();

if(str.indexOf("\r\n")==-1)
return ;
String output = str.substring(0, str.indexOf("\r\n"));
ByteBuffer outBuffer = charset.encode(output);
SocketChannel socketChannel = (SocketChannel)key.channel();
while (outBuffer.hasRemaining())
socketChannel.write(outBuffer);

if (output.equals("bye\r\n")) {
key.cancel();
socketChannel.close();
System.out.println("关闭与客户的连接");
}
}

public static void main(String[] arg){
try {
new MyServer().server();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}



客户端

package nonblock;
import java.net.*;
import java.nio.channels.*;
import java.nio.*;
import java.io.*;
import java.nio.charset.*;
import java.util.*;

public class MyClient {
private SocketChannel socketChannel = null;
private ByteBuffer sendBuffer = ByteBuffer.allocate(1024);
private ByteBuffer receiveBuffer = ByteBuffer.allocate(1024);
private Charset charset = Charset.forName("GBK");
private Selector selector;

public MyClient() throws IOException {
socketChannel = SocketChannel.open();
InetAddress ia = InetAddress.getLocalHost();
InetSocketAddress isa = new InetSocketAddress(ia, 8000);
socketChannel.connect(isa);
socketChannel.configureBlocking(false);
System.out.println("与服务器的连接建立成功");
selector = Selector.open();
}

public static void main(String args[]) throws IOException {
final MyClient client = new MyClient();
// Thread receiver = new Thread() {
// public void run() {
// client.receiveFromUser();
// }
// };
//
// receiver.start();
client.talk();
}

private void talk() throws IOException {
// TODO Auto-generated method stub
socketChannel.register(selector, SelectionKey.OP_READ
| SelectionKey.OP_WRITE);
while(selector.select()>0){
Set keySet = selector.selectedKeys();
Iterator iter = keySet.iterator();
while(iter.hasNext()){
SelectionKey key = (SelectionKey)iter.next();
iter.remove();
if(key.isWritable()){
// send(key);
System.out.println("客户端可写...");
}
if(key.isReadable()){
System.out.println("客户端可读...");
}
}
}
}

public void send(SelectionKey key) throws IOException {


SocketChannel socketChannel = (SocketChannel)key.channel();
String input ;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

Charset charset = Charset.forName("GBK");

while((input=br.readLine())!=null){
ByteBuffer buffer = ByteBuffer.allocate(2);
ByteBuffer outBuffer = ByteBuffer.allocate(2);
buffer= charset.encode(input+"\r\n");
// outBuffer.put(buffer);
// buffer.flip();
socketChannel.write(buffer);
buffer.flip();
System.out.println("I say:"+ charset.decode(buffer).toString());
}
}
}


运行后,服务器端显示:
Serve 启动了!
此时运行客户端,服务器端显示:
服务器端接收到连接...
客户端信息/172.30.0.8:1766
服务器完成注册...
服务器端可以写入信息...
服务器端可以写入信息...
.
.
.
而客户端一直循环显示:
客户端可写...
客户端可写...
客户端可写...
.
.
.

当服务器端运行后,便首先使用register方法,是的当前的ServerSocketChannel可以进行OP_ACCEPT,此时运行客户端,则客户端便SocketChannel使用register方法,是的可以Selector可以对OP-READ和OP_WRITE进行等待并执行,与此同时,服务器发现客户端有链接,激活了Selectot的OP_ACCEPT,便建立连接,使用accept接收了SocketChannel的连接,此后SocketChannel便成了服务器端与客户端操作的通道!此时服务器端和当前的客户端都有一个SocketChannel,而SocketChannel是联通的!而服务器端和客户端此时共同维持一个缓冲区,可以对这个缓冲区进行读写操作。而这个缓冲区就是SocketChannel的register操作时的产生的!
个人理解,如有不对的,望大家指出!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值