Android端 - 通过Socket以及TCP协议和MFC端通信(Receive篇)

Android端 - 通过Socket以及TCP协议和MFC端通信(Receive篇)

前言

  1. 上一篇 Android端 - 通过Socket以及TCP协议和MFC端通信(Send篇); 中说到,接到一功能要求,Android 端实现在 WIFI 局域网的条件下和 PC 端通信;
  2. 上一篇实现了手机端 发送;本文将实现 手机端接收文件!

PC端

  1. 发送文件信息:MD5$fileName$fileSize

  2. 接收 Android 端发送来的接受验证;即手机端按照该文件本地是否存在,返回 “YES” 与否;

  3. 对 Android 端发送来的信息判断,如果是 “YES” 就继续发送文件;否则完成一次信息发送;

  4. PS:这里由于 Android 端发送的 “YES” 始终不被 PC 端接收,故砍掉此鸡肋,改用发送结构体;

  5. 结构体如下:

    //SendMD5andLogDlg.h : 头文件中
    typedef struct  
    {
    	int nMsgCode;
    	double pdDataX[2];
    	double pdDataY[2];
    	int nDataCnt;
    }ST_MSG;
    
  6. 取消 C++ 自动的字节对齐:

    //SendMD5andLogDlg.h : 头文件中
    #pragma once
    #pragma pack(push,1) //主要添加这一句!
    
    ……
    
    #pragma(pop)//末尾一天给添加这一句
    

Android端

  1. 开启线程循环监听端口;

    try{
    	ss = new ServerSocket();
    	ss.setReuseAddress(true);
    	ss.bind(new InetSocketAddress(port));
    }catch(){……
    }
    
    Thread receiveFileThread = new Thread(new Runnable() {
      @Override
        public void run() {
            while (true) {
                ReceiveFile();
            }
        }
    });
    receiveFileThread.start();
    
  2. 接收 PC 端发送来的文件信息,进行处理,读取到 MD5码、文件名、文件大小;这里要注意对编码进行验证,或者使用 “GBK”;这样可以 解决汉字乱码问题

    void ReceiveFile() {
        try {
            //2. 连接客户端对象;阻塞式方法,只有客户端连接了才会继续往下运行
            while (true) {
                Socket receiveSocket = ss.accept();
                //3.获取客户端发来的数据
                InputStream receiveIPS = receiveSocket.getInputStream();
                //确定 首次发送过来的文件 的编码集,解决汉字乱码问题;
                String code = TxtUtils.getTxtformat(receiveIPS);
                //4.开始 接收 发送文件请求信息
                byte[] bytes = new byte[128];
                receiveIPS.read(bytes);
                /**
                 * 解析获取到的文件信息;并分离出 MD5、Name 以及文件大小;
                 */
                String bytesName = new String(bytes, code).trim();
                MD5R = bytesName.substring(0, bytesName.indexOf("$"));
                isExistMD5(MD5R);
                if(isExistR){
                    Log.i(TAG, "ReceiveFile: 文件已存在");
                    break;
                }
                //去掉MD5
                bytesName = bytesName.replaceAll(MD5R, "");
                //返回一个新字符串
                bytesName = bytesName.substring(1, bytesName.length());
                fileNameR = bytesName.substring(0, bytesName.indexOf("$"));
                String fileSize = bytesName.replaceAll(fileNameR, "");
                fileSize = fileSize.substring(1, fileSize.length());
                receiveIPS = null;
    
    			……
    
  3. 向 PC 端发送结构体;

     //TODO:3.  返回消息给发送端YES;PC端不是 C++,而是MFC框架,所以……
     // 不要使用DataInputStream和DataOutputStream。用InputStream和OutputStream的方式发送“字节流”
    OutputStream PCStructOPS = receiveSocket.getOutputStream();
    PCStructOPS.write(new PcStruct(2, 3, 4.1, 4.2, 4.3, 4.4).getBuf());
    PCStructOPS.flush();
    

    注:具体结构体 发送、接收逻辑见我的博客:Java和C++通过Socket传递结构体

  4. 循环接收文件信息;

    /**
     * 5. 写入文件;确定接收后,正式接收文件
     */
    while (true) {
        //接受文件内容
        //3. 获取客户端发送过来的数据
        InputStream receiveDataIPS = receiveSocket.getInputStream();
        //得到SD卡根目录
        File sdCardDir = Environment.getExternalStorageDirectory();
        //打开data目录,如不存在则生成
        File buildDir = new File(sdCardDir, "/A2ATranfer/data");
        if (!buildDir.exists()) buildDir.mkdirs();
        String savePath = buildDir.getPath() + "/" + fileNameR;
        savePath = savePath.replaceAll(regEx, "");
        //装载文件名的数组
        byte[] buffer = new byte[1024];
        int size = -1;
        //方式二
        long received = 0L;
        FileOutputStream fileOut = new FileOutputStream(new File(savePath), false);
        while (true) {
            size = receiveDataIPS.read(buffer);
            if (size < 0) {
                break;
            }
            //从网络读取,写入到文件
            fileOut.write(buffer, 0, size);
            fileOut.flush();
            received += size;
            if (!(received < Long.parseLong(fileSize))) {            break;
            }
        }
        fileOut = null;
        //重置接收文件判断,因为发送的第一次是数据信息,第二次才是数据内容。不接受第一次就没有文件名信息
        //告诉发送端我已经接收完毕
        MD5R = "";
        break;
    }
    

    注:

    1. 以下列出核心代码,对于大括号以及catch语句自行补全;
    2. 对于文件是否存在利用 MD5 码来进行校验,应将 MD5 存入本地数据库;我这里仅使用集合进行判断存储是不合适的,故没有上传代码;

注意

  1. 对于 Android 端,通过 Socket 发送和接收时,如果先发送,通过 Socket name = new Socket(ipAddress, port); 得到了 Socket ,接下来接收时只需要:InputStream inputStream = name.getInputStream();

  2. 而如果先接收,后需要发送时;通过 以下获得 Socket ;

    ServerSocket ss = new ServerSocket(port);
    Socket receiveSocket = ss.accept();
    InputStream receiveIPS = receiveSocket.getInputStream();
    

    需要发送时只需要:OutputStream PCStructOPS = receiveSocket.getOutputStream();而不要再次 new Socket(Ip,port);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liusaisaiV1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值