java nio

package test;


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;


import java.net.InetSocketAddress;


import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;


import java.util.Iterator;


public class NewSocketServer {
    private static final int port = 9527;
    private Selector selector;
    private ByteBuffer clientBuffer = ByteBuffer.allocate(1024);
    private CharsetDecoder decoder = Charset.forName("GB2312").newDecoder();
    private CharsetEncoder encoder = Charset.forName("GB2312").newEncoder();
    //编码解码格式设置成GBK也行.UTF-8不行,中文乱码  (前提都是客户端没有设置任何编码解码格式)


    public void setListener() throws Exception {
        selector = Selector.open(); //打开选择器
        ServerSocketChannel server = ServerSocketChannel.open(); //定义一个 ServerSocketChannel通道
        server.socket().bind(new InetSocketAddress(port)); // ServerSocketChannel绑定端口
        server.configureBlocking(false); //配置通道使用非阻塞模式
        server.register(selector, SelectionKey.OP_ACCEPT); //该通道在selector上注册  接受连接的动作
        while (true) {
            selector.select(); //select() 会阻塞,直到在该selector上注册的channel有对应的消息读入
            Iterator iter = selector.selectedKeys().iterator();
            while (iter.hasNext()) {
                SelectionKey key = (SelectionKey)iter.next();
                iter.remove(); // 删除此消息
                process(key); // 当前线程内处理。(为了高效,一般会在另一个线程中处理此消息)
            }
        }
    }


    private void process(SelectionKey key) throws IOException {
        if (key.isAcceptable()) { // 接收请求
            ServerSocketChannel server = (ServerSocketChannel)key.channel();
            SocketChannel channel =
                server.accept(); //类似于io的socket,ServerSocketChannel的accept函数返回 SocketChannel
            channel.configureBlocking(false); //设置非阻塞模式
            SelectionKey sKey = channel.register(selector, SelectionKey.OP_READ);
            sKey.attach("read_command"); //这儿接收到连接请求之后可以为每个连接设置一个ID
        } else if (key.isReadable()) { // 读信息
            SocketChannel channel = (SocketChannel)key.channel();
            String name = (String)key.attachment();
            
            if (name.equals("read_command")) {
                int count = channel.read(clientBuffer);
                if (count > 0) {
                    clientBuffer.flip();
                    CharBuffer charBuffer = decoder.decode(clientBuffer);
                    String command =charBuffer.toString(); //command形如:get abc.png 或者  put aaa.png
                    System.out.println("command====" +command); //得到客户端传来的命令
                    String[] temp = command.split(" ");
                    command = temp[0]; //命令  是put还是get
                    String filename = temp[1]; //文件名
                    SelectionKey sKey = channel.register(selector, SelectionKey.OP_WRITE);
                    if (command.equals("put"))
                        sKey.attach("UploadReady#" + filename); //要保护该通道的文件名
                    else if (command.equals("get")) {
                        if (!new File("C:\\temp\\", filename).exists()) { //假设文件都是在C盘根目录
                            System.out.println("没有这个文件,无法提供下载!");
                            sKey.attach("notexists");
                        } else
                            sKey.attach("DownloadReady#" + filename); //要保护该通道的文件名
                    }
                } else {
                    channel.close();
                }
            } else if (name.startsWith("read_file")) { //这儿可以新开一个线程     文件操作也可以用NIO
                DataOutputStream fileOut =
                    new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File("C:\\temp\\",
                                                                                                name.split("#")[1]))));
                int passlen = channel.read(clientBuffer);
                while (passlen >= 0) {
                    clientBuffer.flip();
                    fileOut.write(clientBuffer.array(), 0, passlen);
                    passlen = channel.read(clientBuffer);
                }
                System.out.println("上传完毕!");
                fileOut.close();
                channel.close();
            }
            clientBuffer.clear();
        } else if (key.isWritable()) { // 写事件
            SocketChannel channel = (SocketChannel)key.channel();
            String flag = (String)key.attachment();
            if (flag.startsWith("downloading")) { //这儿可以新开一个线程   文件操作也可以用NIO
                DataInputStream fis =
                    new DataInputStream(new BufferedInputStream(new FileInputStream(new File("C:\\", flag.split("#")[1]))));
                byte[] buf = new byte[1024];
                int len = 0;
                while ((len = fis.read(buf)) != -1) {
                    channel.write(ByteBuffer.wrap(buf, 0, len));
                }
                fis.close();
                System.out.println("文件传输完成");
                channel.close();
            } else if (flag.equals("notexists")) {
                //channel.write(encoder.encode(CharBuffer.wrap(flag)));
                channel.write(ByteBuffer.wrap(flag.getBytes())); //不用编码也行    客户端直接接收    中文也不是乱码
                channel.close();
            } else if (flag.startsWith("UploadReady")) {
                channel.write(encoder.encode(CharBuffer.wrap("UploadReady"))); //这儿如果不重新注册该通道的读操作    selector选择到该通道的将继续永远是写操作,也就无法跳转到上面的接受上传的处理
                SelectionKey sKey = channel.register(selector, SelectionKey.OP_READ); //register是覆盖的????!!!
                sKey.attach("read_file#" + flag.split("#")[1]);
                //key.attach("read_file#"+flag.split("#")[1]); //select不到读操作
            } else if (flag.startsWith("DownloadReady")) {
                channel.write(ByteBuffer.wrap("准备下载".getBytes()));
                //channel.write(encoder.encode(CharBuffer.wrap("准备下载")));
                key.attach("downloading#" + flag.split("#")[1]);
            }
        }
    }


    public static void main(String[] args) {
        try {
            System.out.println("等待来至" + port + "端口的客户端连接.....");
            new NewSocketServer().setListener();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}





///client

package test;


import java.io.*;


import java.net.InetAddress;
import java.net.Socket;


import java.util.Scanner;


public class ClientMain {
    private int ServerPort = 9527;
    private String ServerAddress = "localhost";
    private String GetOrPut = "get";
    private String local_filename = "";
    private String remote_filename = "";
    private byte[] buf;
    private int len;


    class SocketThread extends Thread {
        @Override
        public void run() {
            try {
                File file = new File("C:\\temp\\", local_filename); //假设文件放在C盘
                if (!file.exists() && GetOrPut.equals("put")) {
                    System.out.println("本地没有这个文件,无法上传!");
                    return;
                }
                //InetAddress loalhost = InetAddress.getLocalHost();
                Socket socket =
                    new Socket(ServerAddress, ServerPort); //服务器IP地址  端口号   本机IP 本机端口号
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                //dos.writeUTF(GetOrPut+" "+remote_filename);//服务器端如果是io的socket,writeUTF和writeUTF对接
                dos.write((GetOrPut + " " + remote_filename).getBytes());
                dos.flush();
                //String tempString = dis.writeUTF();
                buf = new byte[1024];
                len = dis.read(buf);
                String tempString = new String(buf, 0, len); //服务器反馈的信息
                //System.out.println(tempString);
                if (tempString.equals("notexists")) {
                    System.out.println("服务器没有这个文件,无法下载!");
                    dos.close();
                    dis.close();
                    socket.close();
                    return;
                }
                if (tempString.startsWith("准备下载")) {
                    DataOutputStream fileOut =
                        new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
                    while ((len = dis.read(buf)) != -1) {
                        fileOut.write(buf, 0, len);
                    }
                    System.out.println("下载完毕!");
                    fileOut.close();
                    dos.close();
                    dis.close();
                    socket.close();
                } else if (tempString.equals("UploadReady")) {
                    System.out.println("正在上传文件.......");
                    DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
                    while ((len = fis.read(buf)) != -1) {
                        dos.write(buf, 0, len);
                    }
                    dos.flush();
                    System.out.println("上传完毕!");
                    fis.close();
                    dis.close();
                    dos.close();
                    socket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    public boolean checkCommand(String command) {
        if (!command.startsWith("put") && !command.startsWith("get")) {
            System.out.println("输入命令错误");
            return false;
        }
        int index = -1;
        String temp = "";
        String[] tempStrings = null;
        if ((index = command.indexOf("-h")) > 0) {
            temp = command.substring(index + 3);
            temp = temp.substring(0, temp.indexOf(' '));
            ServerAddress = temp;
        }
        if ((index = command.indexOf("-p")) > 0) {
            temp = command.substring(index + 3);
            temp = temp.substring(0, temp.indexOf(' '));
            ServerPort = Integer.valueOf(temp);
        }
        tempStrings = command.split(" ");
        if (command.startsWith("put")) {
            GetOrPut = "put";
            local_filename = tempStrings[tempStrings.length - 2];
            remote_filename = tempStrings[tempStrings.length - 1];
        } else if (command.startsWith("get")) {
            GetOrPut = "get";
            local_filename = tempStrings[tempStrings.length - 1];
            remote_filename = tempStrings[tempStrings.length - 2];
        }
        return true;
    }


    public static void main(String[] args) {
        ClientMain thisC = new ClientMain();
        Scanner sc = new Scanner(System.in);
        String commandString = "";
        do {
            System.out.println("请输入命令:");
            commandString = sc.nextLine();
        } while (!thisC.checkCommand(commandString));
        ClientMain.SocketThread a = thisC.new SocketThread();
        a.start();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值