关闭

Android 实现只创建一个socket就能一次传输多个文件

标签: androidsocketjava
290人阅读 评论(0) 收藏 举报
分类:

Android 实现一个socket传输多个文件

在网上看到好多关于socket的文章都是创建一次socket只传输一个文件,这种方式如果在需要一次传多文件的情况下,要创建很多个socket,显然这样的效率是不好的,所以我写了一个socket一次传多个文件的demo,没code说个屌,代码如下:

1.server socket

public class RespMultiFileListThread extends Thread {
    private static final String TAG = "RespMultiFileListThread";

    public boolean mIsRunThread = true;

    private DataInputStream in;
    private DataOutputStream out;
    Socket client;

    private Intent mIntent;
    private Context mContext;

    private DeviceBean mDeviceBean;

    public RespMultiFileListThread(Context context, Socket client) {
        this.mContext = context;
        this.client=client;
        this.start();

        initDeviceData();
    }

    public void run() {
        File file ;
        byte[] fileTempBytes = new byte[1024];
        int len = -2;
        FileInputStream fis;
        String rawCmd = "";

        try {
            in = new DataInputStream(client.getInputStream());
            out = new DataOutputStream(client.getOutputStream());
            rawCmd = in.readUTF();
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        //获取请求命令
        if(! rawCmd.equals("req_thumb_list")){
            try {
                in.close();
                out.close();
                client.close();
            } catch (IOException e) {
            }
            return;
        }

        //返回设备文件信息
        try {
            out.writeUTF(new Gson().toJson(mDeviceBean));
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        if(mDeviceBean == null ){
            return ;
        }

        HashMap<String , Long> thumbMap = mDeviceBean.getFileMap();

        if(thumbMap == null ||thumbMap.size() == 0){
            try {
                in.close();
                out.close();
                client.close();
            } catch (IOException e) {
            }
            return;
        }

        Set set = thumbMap.entrySet() ;
        Iterator it = thumbMap.entrySet().iterator();
        Entry entry;
        while (it.hasNext()) {
            entry = (Entry) it.next();

            try {
                String fileName = in.readUTF();
                Log.i(TAG, fileName);

                file = new File(MyApplication.mFilesPath+"/" + fileName);
                fis = new FileInputStream(file);

                while ((len = fis.read(fileTempBytes, 0, fileTempBytes.length)) != -1) {
                    out.write(fileTempBytes, 0, len);  
                    out.flush();  
                }
                if(len == -1){
                    Log.i(TAG, "send completed");
                }
            } catch (IOException e) {
                Log.i(TAG, e.toString());
                e.printStackTrace();
                Log.i(TAG, "客户端已下线,结束本次");
            }
        }

        try {
            client.close();
        } catch (IOException e) {
        }

    }

    private void initDeviceData(){
        mDeviceBean = new DeviceBean();
        mDeviceBean.setDeviceName(Build.MANUFACTURER +" " + Build.MODEL);
        mDeviceBean.setDeviceType("android");
        mDeviceBean.setMacAddr(PhoneInfoUtils.getMacAddr(mContext));
        mDeviceBean.setLanGroupId(MyApplication.mLanGroupId);

        //TODO thumb path
        HashMap<String, Long> fileMap = FileUtils.getFileMap(MyApplication.mFilesPath);
        mDeviceBean.setFileMap(fileMap);
        mDeviceBean.setIpAddr(NetWorkUtils.getWifiIp(mContext));
    }

2.client socket

 public ReqMultiFileClientThread(Context context, Handler handler, String ip , int port ,String formMac) {
        this.mHandler = handler;
        this.mFromDeviceMac = formMac;
        this.mIp = ip;
        this.mPort = 1241;
    }

    private void connectServer(String ip, int port) {
        if (!mIsFirstCreate) {
            mHandler.sendEmptyMessage(MSG_TRYING_CONNECT);
        }
        try {
            if(!mIsCanConnect || !mIsSetReConnect){
                return;
            }

            Log.i(TAG, "正在尝试连接服务器...");
            mIsCanConnect = false;
            mClient = new Socket();
            mClient.connect(new InetSocketAddress(ip, port), TIME_OUT_CONNECT);
            mClient.setSoTimeout(TIME_OUT_READ_DATA);
            Log.i(TAG, "连接服务器成功:" + ip + "   " + port);
            in = new DataInputStream(mClient.getInputStream());
            out = new DataOutputStream(mClient.getOutputStream());
            mIsRunThread = true;
            if (mIsFirstCreate) {
                mIsFirstCreate = false;
            } else {
                this.run();
            }
            mHandler.sendEmptyMessage(MSG_CONNECT_OK);
        } catch (IOException e) {
            mIsCanConnect = true;
            mHandler.sendEmptyMessage(MSG_CONNECT_FAILD);
            Log.i(TAG, "连接服务器失败:" + ip + "   " + port);
            try {
                sleep(3*1000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            connectServer(mIp, mPort);
        }
    }

    public void run() {
        connectServer(mIp, mPort);
        Log.i(TAG, "ReqMultiFileClientThread running");
        File saveFolder = new File(MyApplication.mReceiveFolder+"/"+mFromDeviceMac);
        if(!saveFolder.exists()){
            saveFolder.mkdirs();
        }
        byte[] fileTempBytes = new byte[1024];
        FileOutputStream mFileOutputStream;
        Message mMessage ;

        Log.i(TAG, "发送thumb请求cmd给服务器请求下载...");
        String thumbListStr;
        try {
            out.writeUTF("req_thumb_list");
            thumbListStr = in.readUTF();
        } catch (IOException e1) {
            e1.printStackTrace();
            try {
                out.close();
                in.close();
            } catch (IOException e) {
            }
            return;
        }

        if(StrUtils.isEnpty(thumbListStr)){
            return ;
        }

        DeviceBean reqDeviceBean;
        try{
            reqDeviceBean = new Gson().fromJson(thumbListStr, DeviceBean.class);
        } catch(JsonSyntaxException e){
            e.printStackTrace();
            return;
        }

        if(reqDeviceBean == null){
            return;
        }

        HashMap<String, Long> thumbMap = reqDeviceBean.getFileMap();
        //一个文件都没有
        if(thumbMap == null || thumbMap.size() == 0){
            return;
        }

        Set set = thumbMap.entrySet() ;
        Iterator it = thumbMap.entrySet().iterator();

        while (it.hasNext()) {
            Entry entry = (Entry) it.next();

            File saveFile = new File(saveFolder.getAbsolutePath() + "/" + entry.getKey());
            String mFileName = entry.getKey()+"";
            mFileLength = (long) entry.getValue();
            float sum = 0;
            int len = -2;
            try {
                mFileOutputStream = new FileOutputStream(saveFile);
                try{
                    out.writeUTF(entry.getKey()+"");
                    while ((len = in.read(fileTempBytes, 0, fileTempBytes.length)) != -1) {
                        mFileOutputStream.write(fileTempBytes, 0, len);
                        mFileOutputStream.flush();
                        sum += len;
                        Log.i(TAG, sum/mFileLength * 100+"%");
                        mHandler.sendEmptyMessage((int) (sum/mFileLength * 100));
                        if(sum == mFileLength){
                            break;
                        }
                    }

                } catch(SocketTimeoutException e){   //服务器断开导致的异常
                    e.printStackTrace();
                    Log.i(TAG, "连接超时!");
                    mIsCanConnect = true;
                } catch(SocketException e){    //本地网络断开导致的异常 
                    e.printStackTrace();
                    Log.i(TAG, "网络断开,连接超时!");
                    mIsCanConnect = true;
                }

                Log.i(TAG, "接收完成");

                mMessage = new Message();
                mMessage.obj = new File(saveFolder.getAbsolutePath()+"/"+mFileName.substring(0, mFileName.length()-2));
                mHandler.sendMessage(mMessage);


            }catch (IOException e) {
                e.printStackTrace();
            }
        }

        mIsRunThread = false;
        try {
            mClient.close();
        } catch (IOException e) {
        }
        mIsCompleted = true;

    }

}

通过请求一个 返回一个文件的方式,可以避免多个文件连续处出现多余或者缺少的发生,比如,设定buffer byte[] 大小为1024,但是实际上某个文件最后一个一次buffer并不刚好是1024,然后会把下一个文件的流数据混合进去,导致上一个文件多了,下一个文件少了,现在通过这种请求再返回文件数据流的方式就可以分隔开来

通过请求一次返回一个文件的方式,可以避免多个文件连续处出现多余或者缺少的发生,比如,设定buffer byte[] 大小为1024,但是实际上某个文件最后一个一次buffer并不刚好是1024,然后会把下一个文件的流数据混合进去,导致上一个文件多了,下一个文件少了,现在通过这种请求再返回文件数据流的方式就可以分隔开来

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:52793次
    • 积分:374
    • 等级:
    • 排名:千里之外
    • 原创:13篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条
    文章分类
    最新评论