Android通过WIFI建立热点,通过scoket实现聊天室,文件传输等通信功能。

最近要做一个手机跟蓝牙模块进行通信的项目,查了一些资料,做出了一个可以实现通信的demo。

这里是把手机作为服务器,开启手机热点。(可以去系统设置里开启热点,也可以代码开启热点)

下面是开启热点的代码(配置文件要加上权限),但是这个方法在Android6.0里面开启不了,我查了一下大家都说加上

WRITE_SETTINGS权限,但是我加上了也不行,只有把
targetSdkVersion 由23改为22了。。。

  /**
     * 判断WIFI热点是否开启
     */
    public boolean isApOn() {
        try {
            Method method = wifiManager.getClass().getDeclaredMethod("isWifiApEnabled");
            method.setAccessible(true);
            return (Boolean) method.invoke(wifiManager);
        }
        catch (Throwable ignored) {}
        return false;
    }
    /**
     * 设置热点名称及密码,并创建热点
     * @param mSSID
     * @param mPasswd
     */
    private Boolean stratWifiAp(String mSSID, String mPasswd,Boolean onoff) {
        Method method1 = null;
        if(onoff){
            wifiManager.setWifiEnabled(false);
        }
       try {
            //通过反射机制打开热点
            method1 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
            WifiConfiguration netConfig = new WifiConfiguration();
            netConfig.SSID = mSSID;
            netConfig.preSharedKey = mPasswd;
            netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
            netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
            netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
            netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
            netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
            netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
            netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
            netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            return (Boolean)method1.invoke(wifiManager, netConfig, onoff);

        } catch (Exception e) {
           return false;
       }
    }


打开后就可以启动服务起了


public void startServer(){
    Thread thread = new Thread(){
        @Override
        public void run() {
            super.run();
                /*指明服务器端的端口号*/
            try {
                server = new ServerSocket(9999);
            } catch (IOException e) {
                e.printStackTrace();
            }
            while (true){

                try {
                    socket = server.accept();
                    in  = socket.getInputStream();
                    handler.sendEmptyMessage(2);
                } catch (IOException e) {
                    e.printStackTrace();
                }

                new ServerThread(socket,in).start();

            }
        }
    };
    thread.start();
}

    class ServerThread extends Thread{

        private Socket socket;
        private InputStream   inputStream;


        public ServerThread(Socket socket,InputStream inputStream){
            this.socket = socket;
            this.inputStream = inputStream;
        }
        @Override
        public void run() {
            byte[]mode=new byte[13];//对话0  文件1

            while (inputStream!= null) {
                for(int i=0;i<13;i++){
                    try {
                        mode[i]=(byte)inputStream.read();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();

                    }
                }
                String modestr =new String(mode);
                //传送的数据模式 0 对话  1 文件
                try {
                    //对话或文件
                    int modeCode = Integer.parseInt(modestr.substring(0, 1), 10);
                    //对话或文件大小
                    long inLength = Long.parseLong(modestr.substring(1, 11), 10);
                    //如果是文件的话文件名长度
                    int nameLength = Integer.parseInt(modestr.substring(11, 13), 10);
                    byte[] fileName = new byte[nameLength];
                    byte[] mgs = new byte[new Long(inLength).intValue()];
                    //设置buff缓存为512字节
                    int inTime=(int)(inLength/512);
                    int inTimeResidue=(int)(inLength%512);

                    if (modeCode == 0) {
                        for (int i = 0; i < inLength; i++) {
                            try {
                                mgs[i] = (byte) inputStream.read();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }

                        reviceMgs = new String(mgs,"UTF-8");
                        Log.e("收到数据", reviceMgs.toString());
                        handler.sendEmptyMessage(1);
                        //  ET_print.getText().append("\n"+new String(mgs));


                    } else if (modeCode == 1) {
                        for (int i = 0; i < nameLength; i++) {
                            try {
                                fileName[i] = (byte) inputStream.read();
                            } catch (IOException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        }
                        reviceName = new String(fileName,"UTF-8");
                        Log.e("收到文件名", reviceName.toString());
                     //   handler.sendEmptyMessage(1);
                         dir = new File("/mnt/sdcard/WifiSocketDownload/"+reviceName);
                        File file = new File("/mnt/sdcard/WifiSocketDownload");
                        if (!file.exists()) {
                            try {
                                //按照指定的路径创建文件夹
                                file.mkdirs();
                                Log.e("创建文件夹成功",file.toString());
                            } catch (Exception e) {
                                // TODO: handle exception
                                Log.e("创建文件夹失败","创建文件夹失败");
                            }
                        }
                        if (!dir.exists()) {
                            try {
                                //在指定的文件夹中创建文件
                                dir.createNewFile();
                                Log.e("创建文件成功",dir.toString());
                            } catch (Exception e) {
                                Log.e("创建文件失败","创建文件失败");
                            }
                        }
                    if(inTime>=0&&inTimeResidue>0) {
                        byte[] buffer = new byte[512];
                        reciveTime= 0;
                        for (int i = 0; i < inTime + 1; i++) {
                            for (int k = 0; k < 512; k++) {
                                try {
                                    buffer[k] = (byte) inputStream.read();
                                } catch (IOException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                            writeFileSdcard(dir, buffer);
                            handler.sendEmptyMessage(99);

                        }

                    }else if(inTime>=0&&inTimeResidue==0){

                        byte[] buffer = new byte[512];
                        reciveTime= 0;
                        for (int i = 0; i < inTime ; i++) {
                            for (int k = 0; k < 512; k++) {
                                try {
                                    buffer[k] = (byte) inputStream.read();
                                } catch (IOException e) {
                                    // TODO Auto-generated catch block
                                    e.printStackTrace();
                                }
                            }
                            writeFileSdcard(dir, buffer);
                            handler.sendEmptyMessage(99);

                        }
                    }
                        handler.sendEmptyMessage(98);
                    }

                }catch (Exception e){

                }
            }
        }
    }


    public void writeFileSdcard(File fileName, byte []wb){
        try{
            //FileOutputStream fout = openFileOutput(fileName, MODE_PRIVATE);
            FileOutputStream fout = new FileOutputStream(fileName,true);
            fout.write(wb);
            fout.close();
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }

while (true){

    try {
        socket = server.accept();
        in  = socket.getInputStream();
        handler.sendEmptyMessage(2);
    } catch (IOException e) {
        e.printStackTrace();
    }

    new ServerThread(socket,in).start();

}


当有客户端连接进来,就启动一个线程
 new ServerThread(socket,in).start();
进行监听

(如果要实现多人群聊的话,就是美有一个客户端进行连接,就把这个客户端保存到list里面然后服务器进行数据转发,我这里没有保存,也没有关闭前一个客户端,如果有两个客户端进行连接的话,服务器发的对话只能最近一个客户端可以收到,但是客户端发给服务器的数据,服务器都能收到)


ServerThread的run方法里对接收到的数据进行处理

byte[]mode=new byte[13];
13个字节为发送过来的头部分,其中第一个字节判断是发送的对话还是文件,第二到11共10字节为发送类容的字节数(比如163字节的类容就表示为0000000163)(好像最大可以是9个多G的样子,一般用不到这么长啦),11到13字节表示文件名长度,如果是对话就是00.

for(int i=0;i<13;i++){
    try {
        mode[i]=(byte)inputStream.read();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();

    }
}
读出13字节的头
//对话或文件
int modeCode = Integer.parseInt(modestr.substring(0, 1), 10);
//对话或文件大小
long inLength = Long.parseLong(modestr.substring(1, 11), 10);
//如果是文件的话文件名长度
int nameLength = Integer.parseInt(modestr.substring(11, 13), 10);
byte[] fileName = new byte[nameLength];
byte[] mgs = new byte[new Long(inLength).intValue()];

对头进行解析 (文件和对话分别处理)


下面是服务器发给客户端发送对话的方法(没有加发送文件,客户端有发送文件,如果服务器要向客户端发送文件,可以用客户端发送文件的方法)

public static Boolean send(Socket socket, byte[] msg) {
        DataOutputStream out=null;
        try {
            out = new DataOutputStream((socket.getOutputStream()));
            String mode ="0";
            String name ="00";
            int mgsLength =msg.length;
            String ll =String.format("%010d", mgsLength);
            String sss=mode+ll+name;
            byte sendByte[] =addBytes(sss.getBytes("UTF-8"),msg);
            Log.e("aa","类容字节"+ Arrays.toString(sendByte));
            out.write(sendByte);
            System.out.println("写入数据");
            return true;
            //  out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("写入数据异常");
            return false;
        }
    }

    public static byte[] addBytes(byte[] data1, byte[] data2) {
        byte[] data3 = new byte[data1.length + data2.length];
        System.arraycopy(data1, 0, data3, 0, data1.length);
        System.arraycopy(data2, 0, data3, data1.length, data2.length);
        return data3;

    }



下面是服务器的部分 

if (!wifiManager.isWifiEnabled()) {
    wifiManager.setWifiEnabled(true);
}

WifiConfiguration config = new WifiConfiguration();
config.SSID = "\"wifisocket\"";
config.preSharedKey = "\"00000000\"";//加密wifi
config.hiddenSSID = true;
config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
//config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
config.status = WifiConfiguration.Status.ENABLED;
int netId = wifiManager.addNetwork(config);

上面是打开WiFi 连接服务WiFi热点的代码


连接上服务器热点后,启动客户端连接服务器:

    public void initClientSocket() {
        try {
            socket = new Socket("192.168.43.1", 9999);
            handler.sendEmptyMessage(1);
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            System.out.println("请检查端口号是否为服务器IP");
            handler.sendEmptyMessage(5);
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            System.out.println("服务器未开启");
            handler.sendEmptyMessage(5);
            e.printStackTrace();
        }
    }

读取服务器信息线程

    private class ReadThread extends Thread{

        @Override
        public void run() {
            byte[]mode=new byte[13];//对话0  文件1
            InputStream inputStream  = null;
            try {
                inputStream = socket.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            while (inputStream!= null) {
                for(int i=0;i<13;i++){
                    try {
                        mode[i]=(byte)inputStream.read();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
//                        try {
//                            Log.e("关闭socket"," socket.close();");
//                            inputStream.close();
//                            socket.close();
//                        } catch (IOException e1) {
//                            e1.printStackTrace();
//                        }
                    }
                }
                String modestr =new String(mode);
                //传送的数据模式 0 对话  1 文件
                try{
                int modeCode=Integer.parseInt(modestr.substring(0,1), 10);
                //对话或文件大小
                int inLength=Integer.parseInt(modestr.substring(1,11), 10);
                //如果是文件的话文件名长度
                int nameLength=Integer.parseInt(modestr.substring(11,13), 10);
                byte[]fileName=new byte[nameLength];
                byte[]mgs=new byte[inLength];

                for(int i=0;i<inLength;i++){
                    try {
                        mgs[i]=(byte)inputStream.read();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if(modeCode==0){
                    reviceMgs=new String(mgs,"UTF-8");
                    Log.e("收到数据",reviceMgs.toString());
                    handler.sendEmptyMessage(3);
                    //  ET_print.getText().append("\n"+new String(mgs));
                }else if (modeCode==1){
                }
                }catch (Exception e){

                }
            }


        }

    }

我们可以设置一个按钮,点击按钮就连接服务器启动线程

就可以在点击时执行

new Thread(runnable).start();//开启线程


Runnable runnable = new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        initClientSocket();
        readThread = new ReadThread();
        readThread.start();
    }
};


下面是像服务器发送对话和文件的方法(发送文件前要选着一个文件路径)

    public static byte[] addBytes(byte[] data1, byte[] data2) {
        byte[] data3 = new byte[data1.length + data2.length];
        System.arraycopy(data1, 0, data3, 0, data1.length);
        System.arraycopy(data2, 0, data3, data1.length, data2.length);
        return data3;

    }

    public static Boolean send(Socket socket, byte[] msg) {
        DataOutputStream out=null;
        try {
            out = new DataOutputStream((socket.getOutputStream()));
            String mode ="0";
            String name ="00";
            int mgsLength =msg.length;
            String ll =String.format("%010d", mgsLength);
            String sss=mode+ll+name;
            byte sendByte[] =addBytes(sss.getBytes("UTF-8"),msg);
            Log.e("aa","类容字节"+ Arrays.toString(sendByte));
            out.write(sendByte);
            System.out.println("写入数据");
            return true;
            //  out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("写入数据异常");
            return false;
        }
    }



    public  Boolean sendfile(Socket socket) {
        DataOutputStream out=null;
        try {
            out = new DataOutputStream((socket.getOutputStream()));
            String mode ="1";

            String[] getname = file_path.split("/");

            String filename=getname[getname.length-1];

            byte filenamebyte[] =filename.getBytes("UTF-8");

            String name =String.format("%02d", filenamebyte.length);

            File file =new File(file_path);

            if (file.exists()) {
                sendtime=0;
                FileInputStream fis = null;
                fis = new FileInputStream(file);
                size = fis.available();
                String filesizeString =String.format("%010d", size);
                String sss=mode+filesizeString+name;
                byte sendByteHead[] =addBytes(sss.getBytes("UTF-8"),filenamebyte);
                out.write(sendByteHead);
                handler.sendEmptyMessage(91);
                int n=512;
                byte buffer[]=new byte[n];
                while((fis.read(buffer,0,n)!=-1)&&(n>0)){
                    System.out.println(Arrays.toString(buffer));
                    System.out.println(new String(buffer));
                    out.write(buffer);
                    handler.sendEmptyMessage(92);
                }
                System.out.println("写入完成");
                handler.sendEmptyMessage(93);
                fis.close();
                return true;
            } else {
                file.createNewFile();
                Log.e("获取文件大小", "文件不存在!");
                return false;
            }

            //  out.flush();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("写入数据异常");
            return false;
        }
    }


源码下载地址:点击打开链接

如果改下包名安装成2个APP,同一个手机也可以同时启动服务器和客户端,下图就是同一pad上进行通信的截图。






猜你喜欢

转载自blog.csdn.net/ink_s/article/details/61913954
今日推荐