Created
January 12, 2020 08:13
-
-
Save honwhy/d5df556383bc13c15ce5cc75f778abc6 to your computer and use it in GitHub Desktop.
用nio写ftpclient(未完)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.example; | |
import java.io.IOException; | |
import java.net.InetSocketAddress; | |
import java.net.SocketException; | |
import java.nio.ByteBuffer; | |
import java.nio.channels.SelectionKey; | |
import java.nio.channels.Selector; | |
import java.nio.channels.SocketChannel; | |
import java.util.ArrayList; | |
import java.util.Iterator; | |
import java.util.Set; | |
import java.util.concurrent.Executor; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.ScheduledExecutorService; | |
import java.util.function.Function; | |
import java.util.logging.Logger; | |
public class MyFTP { | |
private static Selector selector; | |
private static ScheduledExecutorService scheduledExecutor; | |
private String hostname; | |
//private int port; | |
protected int _replyCode; | |
protected ArrayList<String> _replyLines; | |
protected boolean _newReplyString; | |
protected String _replyString; | |
protected String _controlEncoding; | |
static { | |
try { | |
selector = Selector.open(); | |
} catch (IOException e) { | |
Logger.getLogger(MyFTP.class.getName()).warning("failed to open selector"); | |
} | |
//TODO set Thread Factory | |
scheduledExecutor = Executors.newSingleThreadScheduledExecutor(); | |
//scheduledExecutor.schedule(); | |
} | |
public static void main(String[] args) throws IOException, InterruptedException { | |
System.out.println("connecting..."); | |
MyFTP myFTP = new MyFTP(); | |
myFTP.connect("localhost", 21); | |
} | |
public void connect(String hostname, int port) | |
throws SocketException, IOException, InterruptedException { | |
this.hostname = hostname; | |
//_connect(InetAddress.getByName(hostname), port, null, -1); | |
SocketChannel ch = SocketChannel.open(); | |
ch.configureBlocking(false); | |
SelectionKey sk = ch.register(selector, SelectionKey.OP_CONNECT|SelectionKey.OP_READ); | |
sk.attach((Function<Void, Void>) nil -> { | |
try { | |
System.out.println("isConnectable" + sk.isConnectable()); | |
if (sk.isConnectable()) { | |
SocketChannel socketChannel = (SocketChannel) sk.channel(); | |
//System.out.println("connected"); | |
socketChannel.finishConnect(); | |
doSelect(); | |
} else if (sk.isReadable()) { | |
System.out.println("isReadable:" + sk.isReadable()); | |
ByteBuffer byteBuffer = ByteBuffer.allocate(256); | |
try { | |
SocketChannel ch2 = (SocketChannel) sk.channel(); | |
int bytesWrite = ch.read(byteBuffer); | |
if (bytesWrite != -1) { | |
MyFTP.this._replyString = new String(byteBuffer.array(), 0, bytesWrite); | |
System.out.println(MyFTP.this._replyString); | |
} | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
//socketChannel.finishConnect(); | |
//ByteBuffer loginBuf = ByteBuffer.wrap("USER user".getBytes()); | |
//socketChannel.write(loginBuf); | |
doSelect(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
return null; | |
}); | |
ch.connect(new InetSocketAddress(hostname, port)); | |
doSelect(); | |
Thread.sleep(10*1000L); | |
} | |
private void doSelect() throws IOException { | |
selector.select(); | |
Set<SelectionKey> sks = selector.selectedKeys(); | |
Iterator<SelectionKey> itr = sks.iterator(); | |
if (itr.hasNext()) { | |
SelectionKey key = itr.next(); | |
Function<Void,?> fun = (Function<Void, ?>) key.attachment(); | |
fun.apply(null); | |
itr.remove(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
很多问题没有搞懂
1.模仿org.apache.commons.net.ftp.FTPClient暴露出来的api应该是阻塞式的,MyFTP应该如何去处理从异步到阻塞呢
2.nio的channel如何确定已经读完了返回了呢,需要阅读ftp协议解析control流和data流吗,end_of_file是一个。
3.如何处理与链接池的关系呢
给MyFTP打上标记,是空闲还是使用中来确定是否新建MyFTP实例,而Selector是所有MyFTP公用的,多路复用与多线程编程是不是有冲突呢
我觉得应该多点从Netty实现中获得参考。