【android学习记录】socket 连接两个android设备 服务器端

/**
 * 服务器端
 * 启动方式: startService(new Intent(this, MySocketService.class));
 * */
public class MySocketService extends Service {

    private static final String TAG = "MySocketService";

    private static final int PORT = 8000;//设置端口

    private ExecutorService mExecutorService=null;//线程池

    private ServerSocket server=null;//erverSocket负责接收客户连接请求

    private static MySocketService instance;

    //PrintWriter是用来操作Unicode, 一般需要处理中文时用PrintWriter好了
    private List<PrintWriter> mWriters=new ArrayList<>();

    private MsgCallBack mCallBack;
    private String mMsg;

    public static MySocketService getInstance(){
        if(instance==null){
            instance=new MySocketService();
        }
        return instance;
    }


    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }


    @Override
    public void onCreate() {
        super.onCreate();
        instance=this;
        Log.d(TAG, "socket服务启动" +GetIpAddress.getIP());
        init();
    }


    public void init(){
        new Thread(mInitRun).start();
    }



    /**
     * 开启服务
     * 建立连接
     * */
    private Runnable mInitRun = new Runnable() {
        @Override
        public void run () {
            try {
                //创建一个ServerSocket类,同时在运行该语句的计算机的指定端口建立一个监听服务。
                server = new ServerSocket(PORT);
                mExecutorService = Executors.newCachedThreadPool();//创建线程池

                Log.e(TAG, "服务器已启动...");

                /**
                 * Client程序需要从Server端获取信息及其他服务时,应创建一个Socket对象:
                 * Socket MySocket = new Socket("ServerComputerName",600);
                 * 两个参数,第一个是欲连接到的Server计算机的主机地址,
                 * 第二个参数是该Server机上提供服务的端口号。
                 * 
                 * Socket对象建立成功后,就可以在ClientServer之间建立一个连接,
                 * 并通过这个连接在两个端口号之间传递数据。
                 * 
                 * 简单来说,ServerSocket一般用于设置端口号和监听,
                 * 真正进行通信的是服务器端的Socket和客户端的Socket                 * ServerSocket进行accept后,就将主动权转让了。
                 * 
                 * */
            
                Socket client = null;

                while (true) {
                    client = server.accept();
                    
                    Log.e(TAG, "客户端已连接...");
             
                    PrintWriter writer = new PrintWriter(
                            new BufferedWriter(new OutputStreamWriter(client.getOutputStream())), true);
                    
                    mWriters.add(writer);
                    mExecutorService.execute(new ClientService(client, writer)); //start a new thread to handle the connection
                }
            } catch (Exception e) {
                Log.e("ServerService", "===错误信息:" + e.getMessage());
                e.printStackTrace();
            }
        }
    };





    /**
     * 遍历客户端集合,给每一个客户端发信息
     * */
    public void sendmsg(String msg){
        mMsg=msg;
        int num =mWriters.size();
        Log.d(TAG, "sendmsg: 发送信息"+msg+" "+num);
        for(int index=0;index<num;index++){
            PrintWriter pout=mWriters.get(index);
            new Thread(new SendMsgRun(pout)).start();
        }
    }


    /**
     * 发送信息的类
     * 需要在线程里进行
     * */
    class SendMsgRun implements Runnable{

        PrintWriter mPrintWriter;

        public SendMsgRun(PrintWriter printWriter){
            mPrintWriter=printWriter;
        }

        @Override
        public void run() {
            try{
                mPrintWriter.println(mMsg);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }




    class ClientService implements Runnable{

        private Socket socket;
        private BufferedReader in=null;
        private String msg = "";
        private PrintWriter mWriter;

        public ClientService(Socket socket,PrintWriter printWriter){
            this.socket=socket;
            mWriter=printWriter;

            try{
                in=new BufferedReader(new InputStreamReader(socket.getInputStream()));
                //客户端只要一连到服务器,便向客户端发送下面的信息。
                msg = "服务器地址:" + this.socket.getInetAddress() + "come toal:" + mWriters.size() + "(服务器发送)";
                sendmsg(msg);
            }catch (IOException e){
                e.printStackTrace();
            }
        }



        @Override
        public void run() {
            try {
                while (true) {
                    if ((msg = in.readLine()) != null) {
                        //当客户端发送的信息为:exit时,关闭连接
                        if (msg.equals("exit")) {
                            System.out.println("ssssssss");
//                            mList.remove(socket);
                            mWriters.remove(mWriter);
                            in.close();
                            msg = "user:" + socket.getInetAddress() + "exit total:" + mWriters.size();
                            socket.close();
                            sendmsg(msg);
                            break;
                            //接收客户端发过来的信息msg,然后发送给客户端。
                        } else {
//                            msg = socket.getInetAddress() + ":" + msg + "(服务器发送)";
//                            if ("startMusic".equals(msg)) {
//                                sendmsg("playMusic");
//                            }
                            if (mCallBack != null) {
                                mCallBack.receive(msg);
                            }
                            //sendmsg(msg);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }


    public void setCallBack(MsgCallBack callBack) {
        this.mCallBack = callBack;
    }

    public void cleanClient () {
//        mList.clear();
        mWriters.clear();
    }




}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章