【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();
    }




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