分享
 
 
 

nio 的使用方法 2

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

前面的可能还是不方便,再具体一点:

package zzzhc;

/**

* @author <a href="zzzhcmailto:zzzhc0508@hotmail.com">zzzhc</a>

*

*/

public interface SocketHandler extends ConnectHandler, ReadWriteHandler {

void onConnected();

void onConnectFailed(String msg);

/**

* 在数据从channel中读出后被调用.

*

*/

void onRead();

/**

* 在要写的数所已写入channnel后被调用.

*

*/

void onWrite();

void onClosed(String msg);

}

//抽象实现

package zzzhc;

import java.io.IOException;

import java.net.SocketAddress;

import java.net.SocketException;

import java.nio.ByteBuffer;

import java.nio.channels.SelectionKey;

import java.nio.channels.SocketChannel;

/**

* @author <a href="zzzhc'mailto:zzzhc0508@hotmail.com">zzzhc </a>

*

*/

public abstract class AbstractSocketHandler implements SocketHandler {

public final static int DEFAULT_BUFFER_SIZE = 2 * 1024;

protected final SelectorProcessor processor;

protected final SocketChannel sc;

protected final ByteBuffer readBuf;

protected final ByteBuffer writeBuf;

protected SocketAddress localAddress;

protected SocketAddress remoteAddress;

protected boolean connected = false;

protected boolean closed = false;

public AbstractSocketHandler(SelectorProcessor processor,

SocketAddress remoteAddress) throws IOException {

this.processor = processor;

this.remoteAddress = remoteAddress;

this.sc = SocketChannel.open();

this.sc.configureBlocking(false);

this.sc.connect(remoteAddress);

int readSize = DEFAULT_BUFFER_SIZE;

int writeSize = DEFAULT_BUFFER_SIZE;

try {

readSize = sc.socket().getReceiveBufferSize();

writeSize = sc.socket().getSendBufferSize();

} catch (SocketException e1) {

}

readBuf = ByteBuffer.allocate(readSize);

writeBuf = ByteBuffer.allocate(writeSize);

processor.register(sc, this, SelectionKey.OP_CONNECT);

}

public AbstractSocketHandler(SelectorProcessor processor,

SocketAddress remoteAddress, ByteBuffer readBuf, ByteBuffer writeBuf)

throws IOException {

this.processor = processor;

this.remoteAddress = remoteAddress;

this.sc = SocketChannel.open();

this.sc.configureBlocking(false);

this.sc.connect(remoteAddress);

readBuf.clear();

writeBuf.clear();

this.readBuf = readBuf;

this.writeBuf = writeBuf;

processor.register(sc, this, SelectionKey.OP_CONNECT);

}

public AbstractSocketHandler(SelectorProcessor processor, SocketChannel sc) {

this.processor = processor;

this.sc = sc;

this.connected = true;

if (this.sc.isBlocking()) {

try {

this.sc.configureBlocking(false);

} catch (IOException e) {

e.printStackTrace();

}

}

int readSize = DEFAULT_BUFFER_SIZE;

int writeSize = DEFAULT_BUFFER_SIZE;

try {

readSize = sc.socket().getReceiveBufferSize();

writeSize = sc.socket().getSendBufferSize();

} catch (SocketException e1) {

}

readBuf = ByteBuffer.allocateDirect(readSize);

writeBuf = ByteBuffer.allocateDirect(writeSize);

processor.register(sc, this, SelectionKey.OP_READ);

}

public AbstractSocketHandler(SelectorProcessor processor, SocketChannel sc,

ByteBuffer readBuf, ByteBuffer writeBuf) {

this.processor = processor;

this.sc = sc;

this.connected = true;

if (this.sc.isBlocking()) {

try {

this.sc.configureBlocking(false);

} catch (IOException e) {

e.printStackTrace();

}

}

readBuf.clear();

writeBuf.clear();

this.readBuf = readBuf;

this.writeBuf = writeBuf;

processor.register(sc, this, SelectionKey.OP_READ);

}

public void onConnected() {

System.out.println("connect to "+this.getRemoteAddress()+" ok");

}

public void onConnectFailed(String msg) {

System.out.println("connect to "+this.getRemoteAddress()+" failed:"+msg);

}

/**

* 如果一次没读完,最后须调用readBuf.compact().

* 如果已读完,须调用readBuf.clear().

*/

public void onRead() {

readBuf.flip();

int len = readBuf.limit();

byte[] buf = new byte[len];

readBuf.get(buf);

readBuf.clear();

System.out.print(new String(buf));

writeBuf.put(buf);

writeBuf.flip();

enableWrite();

}

public void onWrite() {

}

public void onClosed(String msg) {

System.out.println("channel closed:"+msg);

}

public void handleConnect() {

try {

if (sc.finishConnect()) {

onConnected();

connected = true;

} else {

onConnectFailed("");

}

processor.addInterestOps(sc, SelectionKey.OP_READ);

} catch (IOException e) {

e.printStackTrace();

onConnectFailed(e.getMessage());

}

}

public void handleRead() {

try {

//System.out.println("read");

int len = sc.read(readBuf);

if (len == -1) {//closed

dispose("channel been closed correct");

} else {

//readBuf.flip();

onRead();

processor.addInterestOps(sc,SelectionKey.OP_READ);

}

} catch (IOException e) {

e.printStackTrace();

dispose(e.getMessage());

}

}

public void handleWrite() {

if (write()==true) {

onWrite();

}

}

/**

* 将writeBuf中的数据写入socketchannel中,如写完清空writeBuf返回true,否则返加false.

* 在使用该方法前应先对writeBuf调用flip()方法.

* @return

*/

protected boolean write() {

if (writeBuf.hasRemaining()) {

try {

sc.write(writeBuf);

} catch (IOException e) {

e.printStackTrace();

dispose(e.getMessage());

return false;

}

}

if (writeBuf.hasRemaining()) {

enableWrite();

return false;

}

else {

writeBuf.clear();

return true;

}

}

public SocketAddress getLocalAddress() {

if (localAddress == null) {

localAddress = this.sc.socket().getLocalSocketAddress();

}

return localAddress;

}

public SocketAddress getRemoteAddress() {

if (remoteAddress == null) {

remoteAddress = this.sc.socket().getRemoteSocketAddress();

}

return remoteAddress;

}

public void dispose(String msg) {

if (!closed) {

closed = true;

processor.closeChannel(sc);

onClosed(msg);

}

}

public boolean isConnected() {

return connected;

}

public boolean isClosed() {

return closed;

}

public void close() {

processor.closeChannel(sc);

}

public void enableRead() {

processor.addInterestOps(sc, SelectionKey.OP_READ);

}

public void enableWrite() {

processor.addInterestOps(sc, SelectionKey.OP_WRITE);

}

}

//使用方法,先在console运行nc -l -p 1234再运行EchoClient

package zzzhc;

import java.io.IOException;

import java.net.InetSocketAddress;

import java.net.SocketAddress;

/**

* @author <a href="zzzhcmailto:zzzhc0508@hotmail.com">zzzhc</a>

*

*/

public class EchoClient extends AbstractSocketHandler {

public EchoClient(SelectorProcessor processor,SocketAddress remote) throws IOException {

super(processor,remote);

}

public static void main(String[] args) throws IOException{

EchoClient client = new EchoClient(SelectorProcessor.getDefaultInstance(),new InetSocketAddress("localhost",1234));

}

}

//复杂一点的

package zzzhc;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.net.InetSocketAddress;

import java.net.SocketAddress;

import java.net.URL;

import java.nio.channels.FileChannel;

/**

* @author <a href="zzzhc'mailto:zzzhc0508@hotmail.com">zzzhc </a>

*

*/

public class SimpleHttpClient extends AbstractSocketHandler {

public final static int START_CONNECT = 0;

public final static int CONNECT_OK = 1;

public final static int CONNECT_FAILED = 2;

public final static int TRY_SEND_REQUEST = 10;

public final static int REQUEST_SENT = 11;

//public final static int RECV_RESPONSE_HEADER = 20;

public final static int RESPONSE_HEADER_END = 21;

public final static int START_DATA_TRANSFER = 30;

public final static int END_DATA_TRANSFER = 31;

protected int status = START_CONNECT;

protected URL url;

protected FileChannel fc;

protected FileOutputStream out;

private StringBuffer header = new StringBuffer();

public SimpleHttpClient(SelectorProcessor processor, SocketAddress remote,

URL url) throws IOException {

super(processor, remote);

this.url = url;

}

public void onConnected() {

super.onConnected();

try {

Thread.sleep(10);

}catch (Exception e){}

status = CONNECT_OK;

fillHeader(url);

enableWrite();

status = TRY_SEND_REQUEST;

}

protected void fillHeader(URL url) {

writeBuf.clear();

writeBuf.put("GET ".getBytes()).put(url.getPath().getBytes()).put(

" HTTP/1.1".getBytes()).put((byte) '\r').put((byte) '\n');

writeBuf.put("Host: ".getBytes()).put(url.getHost().getBytes()).put((byte) '\r')

.put((byte) '\n');

writeBuf.put((byte) '\r').put((byte) '\n');

writeBuf.flip();

}

public void onConnectFailed(String msg) {

super.onConnectFailed(msg);

status = CONNECT_FAILED;

System.exit(0);

}

public void onRead() {

readBuf.flip();

switch (status) {

case REQUEST_SENT:

int pos = readBuf.limit();

byte b;

while (readBuf.hasRemaining()) {

b = readBuf.get();

if (b == '\r') {

if (pos - readBuf.position() >= 3) {

b = readBuf.get();//\n

b = readBuf.get();

if (b == '\r') {

b = readBuf.get();//\n

readBuf.compact();

status = RESPONSE_HEADER_END;

return;

}

}

}

}

readBuf.position(pos);

readBuf.limit(readBuf.capacity());

break;

case RESPONSE_HEADER_END:

status = START_DATA_TRANSFER;

case START_DATA_TRANSFER:

System.out.println("start data transfer.");

if (out == null) {

String file = url.getFile().trim();

if ("".equals(file)) {

file = "index.html";

}

int idx = file.lastIndexOf('/');

if (idx != -1) {

file = file.substring(idx + 1);

}

if ("".equals(file)) {

file = "index.html";

}

try {

System.out.println("open "+file+" to write.");

out = new FileOutputStream(file);

fc = out.getChannel();

} catch (FileNotFoundException e) {

//this should not happend.

e.printStackTrace();

close();

}

}

try {

while (readBuf.hasRemaining()) {

fc.write(readBuf);

}

} catch (IOException e) {

e.printStackTrace();

close();

}

readBuf.clear();

break;

default:

System.out.println("status:"+status);

}

}

public void onClosed(String msg) {

super.onClosed(msg);

try {

if (out != null) {

out.close();

fc.close();

}

} catch (IOException e) {

e.printStackTrace();

}

System.exit(0);

}

public void onWrite() {

status = REQUEST_SENT;

System.out.println("request sent.");

}

public static void main(String[] args) throws IOException{

URL url = new URL("http://www.sohu.com/");

new SimpleHttpClient(SelectorProcessor.getDefaultInstance(),new InetSocketAddress("www.sohu.com",80),url);

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有