Android客户端与Unity服务器端进行Socket通讯

一、Android客户端
  • 创建可缓存线程池:Executors.newCachedThreadPool();该方法返回的是一个ExecutorService接口,而这个接口继承Executor接口,Executor只包含一个execute()。
  • execute()方法的参数为一个Runnable,返回值为void。
  • Message类:获取Message对象的最好方法是调用Message.obtain()或者Handler.obtainMessage(),  这样是从一个可回收对象池中获取Message对象。


  • 添加权限:Android客户端与Unity服务器端进行Socket通讯
  • 在MainActivity中初始化界面元素,绑定按钮监听事件,注册广播来发送信息

    private void findView() {
        btnStartClient = (Button) findViewById(R.id.btn_tcpClientConn);
        btnCloseClient = (Button) findViewById(R.id.btn_tcpClientClose);
        btnClientSend = (Button) findViewById(R.id.btn_tcpClientSend);
        editClientPort = (EditText) findViewById(R.id.edit_tcpClientPort);
        editClientIp = (EditText) findViewById(R.id.edit_tcpClientIp);
        editClientSend = (EditText) findViewById(R.id.edit_tcpClientSend);
        MsgList = (TextView) findViewById(R.id.txt_MsgList);
    }

    private void bindListener() {
        btnStartClient.setOnClickListener(myBtnClicker);
        btnCloseClient.setOnClickListener(myBtnClicker);
        btnClientSend.setOnClickListener(myBtnClicker);
    }

    private void bindReceiver() {
        IntentFilter intentFilter = new IntentFilter("tcpClientReceiver");
        registerReceiver(myBroadcastReceiver, intentFilter);//注册广播
    }

    private void Init() {
        btnCloseClient.setEnabled(false);
        btnClientSend.setEnabled(false);

    }

  • 实现按钮“连接服务器”“关闭连接”“发送信息”的点击事件
      public void onClick(View view) {
            switch (view.getId()) {
                case R.id.btn_tcpClientConn:
                    btnStartClient.setEnabled(false);
                    btnCloseClient.setEnabled(true);
                    btnClientSend.setEnabled(true);
                    String ip=editClientIp.getText().toString();
                    String port=editClientPort.getText().toString();
                    tcpClient = new TcpClient(ip, getPort(port));
                    exec.execute(tcpClient);
                    break;
                case R.id.btn_tcpClientClose:
                    tcpClient.closeSelf();
                    btnStartClient.setEnabled(true);
                    btnCloseClient.setEnabled(false);
                    btnClientSend.setEnabled(false);
                    break;
                case R.id.btn_tcpClientSend:
                    SendMsg = editClientSend.getText().toString();
                    Message message = Message.obtain();
                    message.what = 2;
                    message.obj = SendMsg;
                    myHandler.sendMessage(message);//显示在消息列表中
                    exec.execute(new Runnable() {
                        @Override
                        public void run() {
                            tcpClient.send(SendMsg);//发送消息
                        }
                    });
                    editClientSend.setText("");
                    break;
            }
      }


  • 处理消息列表

    private class MyHandler extends android.os.Handler {
        private WeakReference mActivity;
        MyHandler(MainActivity activity) {
            mActivity = new WeakReference(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            if (mActivity != null) {
                switch (msg.what) {
                    case 1://读取到的消息
                        MsgList.append("服务器:" + msg.obj.toString() + "\n");
                        break;
                    case 2://我发送的消息
                        MsgList.append("我:" + msg.obj.toString() + "\n");
                        break;
                }
            }
        }
    }

  • 新建TcpClient类,实现Runnable接口,创建客户端Socket对象,来接收、发送消息
  1. PrintWriter输出流,实现发送消息
  2. DataInputStream,实现接收消息

    public void send(String msg) {
        pw.println(msg);
        pw.flush();
    }
   @Override
    public void run() {
        try {
            socket = new Socket(serverIP, serverPort);
            socket.setSoTimeout(5000);
            pw = new PrintWriter(socket.getOutputStream(), true);
            mInputStreams = socket.getInputStream();
            mDataInputStream = new DataInputStream(mInputStreams);
        } catch (IOException e) {
            e.printStackTrace();
        }
        while (isRun) {
            try {
                rcvLen = mDataInputStream.read(buff);//接收消息
                rcvMsg = new String(buff, 0, rcvLen, "utf-8");
                Intent intent = new Intent();
                intent.setAction("tcpClientReceiver");
                intent.putExtra("tcpClientReceiver", rcvMsg);
                MainActivity.context.sendBroadcast(intent);//将消息发送给主界面
                if (rcvMsg.equals("QuitClient")) {
                    isRun = false;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            pw.close();
            mInputStreams.close();
            mDataInputStream.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

  • 处理接收到的消息,显示在消息列表中
  
    private class MyBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String mAction = intent.getAction();
            switch (mAction) {
                case "tcpClientReceiver":
                    String msg = intent.getStringExtra("tcpClientReceiver");//msg:读取到的消息
                    Message message = Message.obtain();
                    message.what = 1;//用户自定义的消息代码,这样接受者可以了解这个消息的信息
                    message.obj = msg;//obj:发送给接收器的任意对象
                    myHandler.sendMessage(message);
                    break;
            }
        }
    }

二、Unity服务器端

   使用TcpListener实现Unity服务器端,具体流程参照http://blog.sina.com.cn/s/blog_1322690230102y3l4.html接下来补充一些功能

  • 持续监听客户端请求
 
     void StartServer()
    {
        /// 1.建立TCP监听器TcpListener对象。
        listener = new TcpListener(IPAddress.Parse(NetworkValue.ip), NetworkValue.port);
        Debug.Log("服务器已开启: ip-" + NetworkValue.ip + "     port-" + NetworkValue.port);
        listener.Start();                                                             ///2.启动监听器

        //侦测连接的客户端
        while (true)
        {
            ///3.等待客户端连接过来
            TcpClient tcpclient = listener.AcceptTcpClient();//已连接的客户端,阻塞方法
            Debug.Log("一个新用户! Client : " + tcpclient.Client.RemoteEndPoint);

            if (_clients.Count < maxConnected)
            {
                //建立玩家连接类(开启每一个玩家的单独线程)
                client = new ClientSocket(tcpclient);
                _clients.Add(client);
            }
            else
            {
                //向该用户发送"已满"
                Thread.Sleep(500);  //暂停线程500ms
                tcpclient.Close();
            }
        }
    }

  • 手动控制信息的发送

    SendBtn.onClick.AddListener(delegate
            {
                sendMsg = inputText.text;
                inputText.text = "";
                textTest.text += "我:" + sendMsg + "\n";
                client.sendQueue.Enqueue(sendMsg);
            });

三、通讯效果:

    Android客户端与Unity服务器端进行Socket通讯 Android客户端与Unity服务器端进行Socket通讯

四、Android与Unity工程源码:





猜你喜欢

转载自blog.csdn.net/weixin_39766005/article/details/82504928