Server端
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 java.util.Objects;
/**
* @decription: 文件传输服务端: java Server dir port
* @author: PENGPANTING740
* @date: 2019/4/25 16:08
*/
public class Server {
private static String dir = "C:\\Users\\pengpanting740\\Desktop\\log\\temp";
private static int port = 8888;
public static void main(String[] args) throws Exception {
if (Objects.nonNull(args) && args.length > 0) {
dir = args[0];
if (args.length > 1) {
port = Integer.parseInt(args[1]);
}
}
System.out.println("dir is: " + dir);
System.out.println("Server start, and listen port is: " + port);
Selector selector = Selector.open();
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ssc.bind(new InetSocketAddress(port));
ssc.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Iterator it = selector.selectedKeys().iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if (key.isAcceptable()) {
System.out.println("isAcceptable");
SocketChannel sc = ssc.accept();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
SocketChannel socketChannel = (SocketChannel)key.channel();
Protocol p = Protocol.deserialize(socketChannel);
if (p.isValid()) {
if (p.getAction() == Protocol.Action.PUT) {
FileUtils.writeToFile(dir, p.getFileName(), p.getBody());
Protocol result = new Protocol();
result.setBody("upload is success".getBytes());
result.setAction(Protocol.Action.PUT);
result.setFileName("ok!");
ByteBuffer bb = result.serialize();
socketChannel.write(bb);
} else if (p.getAction() == Protocol.Action.GET) {
ByteBuffer bb = FileUtils.downloadFile(dir, p);
socketChannel.write(bb);
}
}
socketChannel.close();
}
it.remove();
}
}
}
}
cleint端
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Objects;
/**
* @decription: 文件传输客户端: java Client ip port fileName
* @author: PENGPANTING740
* @date: 2019/4/25 16:59
*/
public class Client {
private static String dir = "C:\\Users\\pengpanting740\\Desktop\\log";
private static String file = "env.txt";
private static String ip = "localhost";
private static int port = 8888;
public static void main(String[] args) throws Exception {
// ip = "192.168.5.19";
if (Objects.nonNull(args) && args.length > 0) {
ip = args[0];
if (args.length > 1) {
port = Integer.parseInt(args[1]);
if (args.length > 2) {
file = args[2];
}
}
}
SocketChannel sc = SocketChannel.open();
sc.configureBlocking(true);
sc.connect(new InetSocketAddress(ip, port));
boolean isUpload = false;
ByteBuffer buffer;
if (isUpload) {
buffer = FileUtils.uploadRequest(dir, file);
} else {
buffer = FileUtils.downloadRequest("env.txt");
}
sc.write(buffer);
Protocol p = Protocol.deserialize(sc);
if (p.getAction() == Protocol.Action.GET) {
FileUtils.writeToFile(dir, p.getFileName(), p.getBody());
}
System.out.println(p);
sc.close();
}
}
协议类Protocol
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Objects;
/**
* @decription: protocol: 4(totalLength):1(action):2(fileNameLength):change(fileName):change(body)
* @author: PENGPANTING740
* @date: 2019/4/26 15:46
*/
public class Protocol {
private Action action = Action.PUT;
private String fileName;
private byte[] body;
private boolean isValid;
public ByteBuffer serialize() {
if (Objects.isNull(this.fileName) || Objects.isNull(this.action)) {
throw new RuntimeException("fileName and action can not be null.");
}
int totalLength = 4 + 1 + 2 + this.fileName.length();
if (Objects.nonNull(this.body)) {
totalLength += this.body.length;
}
ByteBuffer buffer = ByteBuffer.allocate(totalLength);
buffer.putInt(totalLength);
buffer.put((byte)action.ordinal());
buffer.putShort((short)this.fileName.length());
buffer.put(this.fileName.getBytes());
if (Objects.nonNull(this.body)) {
buffer.put(this.body);
}
buffer.flip();
return buffer;
}
public static Protocol deserialize(SocketChannel channel) throws Exception {
Protocol p = new Protocol();
ByteBuffer totalLengthBuffer = ByteBuffer.allocate(4);
int length = -1;
while (totalLengthBuffer.hasRemaining()) {
length = channel.read(totalLengthBuffer);
if (length < 0) {
break;
}
Thread.sleep(5);
}
if (length > -1) {
totalLengthBuffer.flip();
int totalLength = totalLengthBuffer.getInt();
ByteBuffer totalBuffer = ByteBuffer.allocate(totalLength - 4);
while (totalBuffer.hasRemaining()) {
length = channel.read(totalBuffer);
if (length < 0) {
break;
}
Thread.sleep(5);
}
if (length > -1) {
totalBuffer.flip();
byte action = totalBuffer.get();
short fileNameLength = totalBuffer.getShort();
byte[] fileName = new byte[fileNameLength];
totalBuffer.get(fileName);
int bodyLength = totalLength - 4 - 1 - 2 - fileNameLength;
if (bodyLength > 0) {
byte[] content = new byte[bodyLength];
totalBuffer.get(content);
p.setBody(content);
}
switch (action) {
case 0:
p.setAction(Action.GET);
break;
case 1:
p.setAction(Action.PUT);
break;
default:
System.out.println("invalid action: " + action);
break;
}
p.setFileName(new String(fileName));
p.setValid(true);
}
} else {
channel.close();
}
return p;
}
public boolean isValid() {
return isValid;
}
public void setValid(boolean valid) {
isValid = valid;
}
public Action getAction() {
return action;
}
public void setAction(Action action) {
this.action = action;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public byte[] getBody() {
return body;
}
public void setBody(byte[] body) {
this.body = body;
}
@Override
public String toString() {
return "Protocol{" +
"action=" + action +
", fileName='" + fileName + '\'' +
", isValid=" + isValid +
'}';
}
static enum Action {
GET,
PUT
;
}
}
工具类FileUtils
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
/**
* @decription: TODO
* @author: PENGPANTING740
* @date: 2019/4/26 17:05
*/
public class FileUtils {
public static void writeToFile(String dir, String fileName, byte[] content) throws Exception {
System.out.println("write file name: " + fileName + " and body length: " + content.length);
FileOutputStream fos = new FileOutputStream(dir + File.separator + fileName);
fos.write(content);
fos.close();
}
public static ByteBuffer downloadFile(String dir, Protocol p) throws Exception {
String fileName = p.getFileName();
FileInputStream fis = new FileInputStream(dir + File.separator + fileName);
int bodyLength = fis.available();
byte[] body = new byte[bodyLength];
fis.read(body);
fis.close();
p.setBody(body);
System.out.println("download file name: " + fileName + " and body length: " + bodyLength);
return p.serialize();
}
public static ByteBuffer uploadRequest(String dir, String fileName) throws Exception {
FileInputStream fis = new FileInputStream(dir + File.separator + fileName);
int bodyLength = fis.available();
byte[] body = new byte[bodyLength];
fis.read(body);
fis.close();
Protocol p = new Protocol();
p.setFileName(fileName);
p.setBody(body);
p.setAction(Protocol.Action.PUT);
ByteBuffer buffer = p.serialize();
return buffer;
}
public static ByteBuffer downloadRequest(String fileName) throws Exception {
Protocol p = new Protocol();
p.setFileName(fileName);
p.setAction(Protocol.Action.GET);
ByteBuffer buffer = p.serialize();
return buffer;
}
}