【Android】学习记录socket 再

/**
 * 服务器端
 * 启动方式: 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();

//            SendMsgRun sendMsgRun=new SendMsgRun(pout);
//            Thread t1=new Thread(sendMsgRun);
//            t1.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();
    }




}
 

/**
 * socket连接,客户端
 *
 * 服务需要注册才可以
 * */

public class ClientService2 extends Service {

    private static final String TAG = "ClientService2";

    private static ClientService2 instance;
    private Socket mSocket;
    private BufferedReader mInput;
    private PrintWriter mOut;
    private String content = "";
    private String mHost;


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


    public void setIp (String ip) {
        this.mHost = ip;
    }


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

    @Override
    public void onCreate () {
        Log.e(TAG, "服务启动");
        super.onCreate();
        instance = this;
    }



    /**
     * 连接调用方法
     * 传入ip地址
     * 开始连接
     * */
    public void conn (String host) {
        if (TextUtils.isEmpty(host))
            return;
        mHost = host;
        Log.d(TAG, "开始连接");
        new Thread(connRun).start();
    }



    /**
     * 用于连接的线程
     * */
    private Runnable connRun = new Runnable() {
        @Override
        public void run () {
            Log.e(TAG, "conn:" + mHost);
            try {
                //服务器ip 端口号
                mSocket = new Socket(mHost, 8000);
                mInput = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
                mOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())), true);
            } catch (IOException ex) {
                ex.printStackTrace();
                Log.e(TAG, "login exception" + ex.getMessage());
            }

            //启动线程,接收服务器发送过来的数据
            new Thread(mHandlerMsg).start();
        }
    };


    public void sendMsg (final String msg) {
        Log.e(TAG, "给服务端发送消息 / " + (mOut == null));
        if (mOut == null || TextUtils.isEmpty(
                msg) || mSocket == null || mSocket.isClosed() || !mSocket.isConnected() || mSocket.isOutputShutdown())
        {
            Log.e(TAG,
                    "给服务端发送消息失败:" + (mSocket == null) + " / closed:" + (mSocket.isClosed()) + " / connected:" +
                            mSocket.isConnected() + " / isoutshutdown:" + mSocket.isOutputShutdown());
            return;
        }
        new Thread(new Runnable() {
            @Override
            public void run () {
                try {
                    mOut.println(msg);
                } catch (Exception e) {
                    Log.e(TAG, "给服务端发送消息异常");
                    e.printStackTrace();
                }
            }
        }).start();
    }


    private Runnable mHandlerMsg = new Runnable() {
        @Override
        public void run () {
            try {
                //不断接收服务器传来的信息
                while (true) {
                    if (!mSocket.isClosed()) {
                        if (mSocket.isConnected()) {
                            if (!mSocket.isInputShutdown()) {

                                content = "";

                                if ((content = mInput.readLine()) != null) {

                                    Log.e("ClientService", "接受信息msg:" + content);

                                    //处理信息
                                    handlerServiceMsg(content);

                                } else {

                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };





    /**
     * 处理接受的信息
     *
     * 主要是发送全局广播
     * */
    public void handlerServiceMsg (String msg) {
        Log.d(TAG, "处理信息:"+msg);

        if(msg.equals("念诗")){
            Log.d(TAG, "念诗");
            Intent NS=new Intent("com.Reeman.broadcast.NianShi");
            sendBroadcast(NS);
        }
    }



}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值