• android开发之socket快传文件以及消息返回


    应用场景:

    两台android机器:一台自建wifi热点,另一台搜索到,连接该wifi热点。之后再通过socket传递消息,文件等,当服务器端接收到消息之后会返回对应的应答消息;

    注意点:接收到消息之后不能直接拔dos关闭了,这样会造成socket关闭; 

    socket关闭只需要一端关闭即可;

    这里发送没有使用缓存发送,每一次writeInt的时候度会直接发送出去,,因此可以不需要flush();

    每一次的发送端的 write 和 接收端的read  必须对应,否则异常出错!

    服务器端socket代码:

    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import com.carspeak.client.entity.NetTransEntity;
    import com.carspeak.terminal.utils.AppUtils;
    import android.content.Context;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    
    /**
     * 服务器端完整socket接收代码(接收客户端的图片)
     * @author huqiang
     *
     */
    public class SocketService implements Runnable{
        private static final String TAG = "SocketService";
    
        private ServerSocket serviceSocket;
        private boolean SCAN_FLAG = false; // 接收扫描标识
        private boolean REV_FLAG = false; // 接收标识
        
        private static String mfilePath = null; // 存放接收文件的路径
    
        private static Context mContext;
        private static SocketService instance; // 唯一实例
        private Thread mThread;
        private boolean IS_THREAD_STOP = false; // 是否线程开始标志
    
        private static Handler mHandler;
        public SocketService()
        {
            try
            {
                serviceSocket = new ServerSocket(4700);
                Log.d(TAG, "建立监听服务器ServerSocket成功");
            } catch (IOException e)
            {
                Log.d(TAG, "建立监听服务器ServerSocket失败");
                e.printStackTrace();
            }
            mThread = new Thread(this);
        }
    
        /**
         * <p>
         * 获取TcpService实例
         * <p>
         * 单例模式,返回唯一实例
         */
        public static SocketService getInstance(Context context,Handler handler,String filepath)
        {
            mContext = context;
            mHandler = handler;
            mfilePath = filepath;
            if (instance == null)
            {
                instance = new SocketService();
            }
            return instance;
        }
    
        public void setSavePath(String fileSavePath)
        {
            Log.d(TAG, "设置存储路径成功,路径为" + fileSavePath);
            this.mfilePath = fileSavePath;
            // REV_FLAG=true;
        }
    
        public SocketService(Context context)
        {
            this();
            mContext = context;
        }
    
        private void scan_recv()
        {
            try
            {
                Socket socket = serviceSocket.accept(); // 接收UDP数据报
    //            socket.setSoTimeout(10*1000); // 设置掉线时间
                Log.d(TAG, "客户端连接成功");
                //通过子线程来循环读取socket的消息
                ListenClientSocket ls = new ListenClientSocket(socket);
                ls.start();
    
            } catch (IOException e)
            {
                e.printStackTrace();
                Log.d(TAG, "客户端连接失败");
                SCAN_FLAG = false;
            }
        }
    
        @Override
        public void run()
        {
            Log.d(TAG, "TCP_Service线程开启");
            while (!IS_THREAD_STOP)
            {
                if (SCAN_FLAG)
                {
                    scan_recv();
                }
            }
        }
    
        public void release()
        {
            if (null != serviceSocket && !serviceSocket.isClosed())
                try
                {
                    serviceSocket.close();
                    serviceSocket = null;
                    Log.d(TAG, "关闭socket成功");
                } catch (IOException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            while (SCAN_FLAG == true)
                ;// 直到SCAN_FLAG为false的时候退出循环
            SCAN_FLAG = false;
            IS_THREAD_STOP = true;
        }
    
        public void startReceive()
        {
            SCAN_FLAG = true; // 使能扫描接收标识
            if (!mThread.isAlive())
                mThread.start(); // 开启线程
        }
    
        public void stopReceive()
        {
            while (SCAN_FLAG == true)
                ;
            SCAN_FLAG = false; // 失能扫描接收标识
        }
        
        /**
         * 监听客户端发送的消息
         * @author huqiang
         *
         */
        class ListenClientSocket implements Runnable
        {
            private boolean IsListening = false;
            private Socket clientSocket;
            private Thread thread;
            public ListenClientSocket(Socket s)
            {
                this.clientSocket = s;
                this.thread = new Thread(this);
            }
            @Override
            public void run() {
                while(clientSocket!=null&&!clientSocket.isClosed()&&IsListening)
                {
                    readMessage(this.clientSocket);
                }
            }
            public void start()
            {
                IsListening = true;
                thread.start();
            }
            public void release()
            {
                IsListening = false;
                if(!clientSocket.isClosed())
                {
                    try {
                        clientSocket.close();
                        clientSocket = null;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    
                }
            }
            public void readMessage(Socket socket) 
            {
                NetTransEntity entity = new NetTransEntity();
                try
                {
                    //分批次接收socket
                    InputStream in = socket.getInputStream();
                    DataInputStream dis = new DataInputStream(in);
                    entity.RequestCode = dis.readInt();
                    entity.params = dis.readUTF();
                    switch(entity.RequestCode)
                    {
                    case 100://
                    case 500://请求升级
                        Log.v(TAG, "请求图片");
                        entity.fileLength = dis.readLong();
                        Log.v(TAG, "接收到文件长度:"+entity.fileLength);
                        if(entity.RequestCode==100)
                        {
                            entity.params = "screen.png";
                        }
                        FileOutputStream fos =new FileOutputStream(new File(mfilePath,entity.params));
                        
                        byte[] sendBytes =new byte[1024];
                        int transLen =0;
                        Log.v(TAG, "----开始接收文件<" + entity.params +">,文件大小为<" + entity.fileLength +">----");
                        while(true){
                            int read =0;
                            read = dis.read(sendBytes);
                            Log.v(TAG, "read="+read);
                            if(read == -1)
                                break;
                            transLen += read;
                            Log.v(TAG, "接收文件进度" +100 * transLen/entity.fileLength +"%...");
                            fos.write(sendBytes,0, read);
                            fos.flush();
                        }
                        Log.v(TAG, "----接收文件<" + entity.params +">成功-------1");
                        entity.filePath = mfilePath + entity.params; //将下载下来的文件名字赋值给entity.filePath
                        Log.v(TAG, "----接收文件<" + entity.params +">成功-------2");
                        break;
                    case 101://请求终止投影
                    case 102://请求待机(超时自动待机)
                    case 103://请求高速自动待机
                        break;
                    case 501://请求固件版本信息
                        break;
                    default://其他请求
                        break;
                    }
    //                dis.close();//会造成关闭socket
    //                socket.shutdownInput();
                    //发送返回消息
                    Log.v(TAG, "----开始发送返回消息-------");
                    DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
                    Log.v(TAG, "发送返回消息 1");
                    dos.writeInt(200);
                    dos.flush();
                    Log.v(TAG, "发送返回消息 2");
                    switch(entity.RequestCode)
                    {
                    case 501: //请求固件版本信息
                        //返回版本号
                        Log.v(TAG, "发送返回消息-返回版本号");
                        String versionCode = AppUtils.getVersionCode(mContext)+"";
                        dos.writeUTF(versionCode);
                        dos.flush();
                        break;
                    case 100:
                    case 101:
                    case 102:
                    case 103:
                    default:
                        dos.writeUTF("success");
                        dos.flush();
                        break;
                    }
    //                dos.close();
    //                socket.close();
                }
                catch(Exception ex)
                {
                    Log.e(TAG, "Exception:"+ex.getMessage());
                    
                }
                finally
                {
                    Message msg = new Message();
                    msg.what = 1;  //说明有socket消息
                    msg.obj = entity;
                    mHandler.sendMessage(msg);
                    release();
                }
            }
            
        }
    }

    对应的客户端socket代码:

    import java.io.BufferedReader;
    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.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.ObjectOutputStream;
    import java.io.OutputStream;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    
    import com.carspeak.client.config.SPConfig;
    import com.carspeak.client.entity.CusMessage;
    import com.carspeak.client.entity.NetTransEntity;
    import com.carspeak.client.util.SPUtils;
    import com.carspeak.client.util.WifiUtils;
    
    import android.content.Context;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    
    /**
     * 连接到终端设备
     * 
     * @author huqiang
     * 
     */
    public class ClientService implements Runnable{
    
    //    AppConfig app;
    //    String filePath;
        NetTransEntity mEntity;
        String ServerIP;
        WifiUtils mWifiUtils;
        private final int SERVER_PORT = 4700;  //服务器端口
        private final int TIME_OUT = 6*1000;  //SOCKET超时时间
        private Context mContext;
        private Handler mHandler;
        public ClientService(Context context,Handler handler,NetTransEntity entity) {
    //        app = (AppConfig) context.getApplicationContext();
    //        this.filePath = filePath;
            this.mEntity = entity;
            mContext = context;
            this.mHandler = handler;
            mWifiUtils = WifiUtils.getInstance(context);
            ServerIP = (mWifiUtils.getServerIPAddress()==null)?"192.168.43.1":mWifiUtils.getServerIPAddress();
        }
    
        /**
         * 向终端发送数据
         * @param path
         * @throws IOException
         * @throws Exception
         */
        private void sendMessage(NetTransEntity entity) throws IOException, Exception {
            // 1.连接服务器
            Socket socket = new Socket();
            Log.v("ConnectTerminalServer", "开始准备socket连接,ServerIP=" + ServerIP+ ";SERVER_PORT=" + SERVER_PORT + ";TIME_OUT=" + TIME_OUT+";当前连接状态:getSSID"+mWifiUtils.getSSID());
            socket.connect(new InetSocketAddress(ServerIP, SERVER_PORT), TIME_OUT);
            
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
            
            Log.v("ClientService", "开始写入请求码:"+entity.RequestCode);
            dos.writeInt(entity.RequestCode); //写入请求码
    //        dos.flush();
            switch(entity.RequestCode)
            {
            case 100://请求图片
            case 500://请求固件升级,发送apk文件
                File file = new File(entity.filePath);
                Log.v("ClientService", "开始写入文件名 file.getName()="+file.getName());
                dos.writeUTF(file.getName());  //第二次写入参数信息
                dos.flush();
                Log.v("ClientService", "开始写入文件长度 file.length()="+file.length());
                dos.writeLong(file.length());  //第三次写入文件的长度
                dos.flush();
                //第四次写入文件
                //传输文件
                FileInputStream fis =new FileInputStream(file);
                byte[] sendBytes =new byte[1024];
                int length =0;
                while((length = fis.read(sendBytes,0, sendBytes.length)) >0){
                    dos.write(sendBytes,0, length);
                    dos.flush();
                }
                fis.close();
                break;
            case 101://请求终止
            case 102://请求待机(超时自动待机)
            case 103://请求高速自动待机
                Log.v("ClientService", "开始写入参数="+(entity.params==null?"params is null":entity.params));
                dos.writeUTF(entity.params==null?" ":entity.params);
                dos.flush();
                break;
            case 501://请求固件版本信息
                dos.writeUTF(" ");
                dos.flush();
                break;
            default://其他请求
                break;
            }
            
            Log.v("ClientService", "即将关闭dos");
    //        dos.close();  //注意这里dos关闭会造成socket关闭,应该使用shutdownOutput
            socket.shutdownOutput();  
            Log.v("ClientService", "shutdownOutput");
            /****************接收返回参数******************/
            DataInputStream dis = new DataInputStream(socket.getInputStream());
            CusMessage cms = new CusMessage();
            Log.v("ClientService", "接收消息 1   dis="+dis);
            cms.code = dis.readInt();
            Log.v("ClientService", "接收消息 2");
            cms.message = dis.readUTF();
            Log.v("ClientService", "接收到终端返回消息,code="+cms.code + ";message="+cms.message);
            switch(entity.RequestCode)
            {
            case 501: //请求固件版本信息
                if(cms.code==200)
                {
                    int terminalVersionCode = Integer.parseInt(cms.message);
                    SPUtils.put(mContext, SPConfig.TerminalVersionCode, -1);
                    Message msg = new Message();
                    msg.what = 501;
                    msg.obj = terminalVersionCode;
                    mHandler.sendMessage(msg);
                    Log.v("ClientService", "接收到终端的消息返回,版本号:"+terminalVersionCode);
                }
                break;
            case 100:
            case 101:
            case 102:
            case 103:
            default:
                break;
            }
            dos.close();
            dis.close();
            socket.close();
        }
    
        @Override
        public void run() {
            try
            {
                sendMessage(this.mEntity);
            }
            catch(IOException ex){
                Log.v("ConnectTerminalServer", ex.getMessage());
            }
            catch (Exception ex) {
                Log.v("ConnectTerminalServer", ex.getMessage());
            }    
        }
    
    }
  • 相关阅读:
    机器学习——集成学习之Boosting
    机器学习——集成学习之Bagging
    Javascript获取html元素的几种方法
    JSTL 标签大全详解
    浅谈web应用的负载均衡、集群、高可用(HA)解决方案
    Spring中ApplicationContext加载机制和配置初始化
    Hibernate注解详解(超全面不解释)
    hibernate注解主键生成策略
    Java中Filter、Servlet、Listener的学习
    注解 @Resource与@Autowired与@Component的使用
  • 原文地址:https://www.cnblogs.com/feijian/p/4468546.html
Copyright © 2020-2023  润新知