Android开发之实现两个手机之间的通讯

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dmk877/article/details/51685656

欢迎转载,转载请注明出处:http://blog.csdn.net/dmk877/article/details/51685656

 

Hello,大家好,今天又来写博客了,项目终于搞完了最近又有时间写写博客了。在上上篇博客中我们学习了Android中网络通讯,并用Socket实现了Android客户端与服务器的通讯,那么这一篇将进一步来完善这一功能,就是要实现两个android手机端的通讯。

如有谬误,欢迎批评指正,如有疑问欢迎留言

通过本篇博客你将学到以下知识点
①Socket的用法
②如何实现两个手机的端的通讯
③JAVA中的流的小知识

1、如何实现两个手机端的通讯

在开始之前我们先来分析以下如何实现这个通讯,首先来考虑这么几个问题
①这种实时的通讯应采取哪种通讯方式
②怎么保证是消息能到达我们想发送的那一方,也就是说A想与B交流怎么保证B收到的消息是A发过来的
③怎么保证消息的实时性,也就是说A发一条消息B能实时收到。
要想回答这三个问题其实不难,读过Android开发之网络通讯详解这篇博客的童鞋应该知道,这种及时性比较高的通讯一般采用Socket这种通讯方式,而对于第二个问题如果想让消息到达我们的指定方,针对A和B需要有一个唯一的标识,这个标识我们可以自己定义,在本文中采用的策略是为A和B定义一个ID来唯一的确定它,在A用户发送消息的时候只要指定它想把消息发送到的那个用户的ID就能保证B收到的消息是A发过来的。保证消息的实时性也就是通过使用Socket来解决的。

2、实现两个手机端通讯的原理图

通讯的过程图解

从上图我们可以清楚的看到整个过程服务器充当的是一个中转的作用,clientSocket1首先会将消息封装成json发送给服务器,服务器解析后再封装将消息发送给clientSocket2。

3、实现两个手机端通讯客户端的实现

客户端的运行效果图(注意:下面是一整张图,是一张图片):

上述运行效果就实现了两个Android机的相互通讯。两个客户端分配的id分别为0和1。在发送消息时需要指定消息的到达方。

3.1 客户端发送消息实现步骤

第一步需要做的当然就是连接到服务器,连接服务器的方法为

clientSocket=new Socket(ip,port);
即设置服务器的ip和端口号,建立连接之后通过while(true)就可以不断的监听服务器是否发送过来消息了。

第二步就是要输入你要发送的好友的id号,这样就能保证你发送的消息能按照你的预期到达接收方。

第三步就是发送消息了在发送消息的时候需要注意,我们是把消息封装成json发过去的,这个json中包含哪些信息呢?有三种信息①消息发送方id②消息的内容③消息到达方id。

封装json的代码如下

  //根据clientSocket.getOutputStream得到BufferedWriter对象,从而从输出流中获取数据
   mWriter=new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(),"utf-8"));
   。。。。。
   //封装成json
   JSONObject json = new JSONObject();
   json.put("to", Integer.parseInt(friendId));
   json.put("msg", msgContent);
   //通过BufferedWriter对象向服务器写数据
   mWriter.write(json.toString()+"\n");
   //一定要调用flush将缓存中的数据写到服务器
   mWriter.flush();
这个json中包含三个信息:①消息到达方id②消息的内容③消息发送方的id。封装后通过BufferWriter的write方法将消息发送到服务器。

3.2 客户端接收消息的实现

这里接收消息是用了while循环不断的监听服务器是否有消息发送过来,如果有消息发送过来则用BufferedReader一行一行的去读取消息的内容,然后显示,实现的主要代码如下:

//根据clientSocket.getInputStream得到BufferedReader对象,从而从输入流中获取数据
     mReader=new BufferedReader(new InputStreamReader(clientSocket.getInputStream(),"utf-8"));
     //根据clientSocket.getOutputStream得到BufferedWriter对象,从而从输出流中获取数据
     mWriter=new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream(),"utf-8"));
     while(isReceivingMsgReady){
      if(mReader.ready()){
       Message msg = handler.obtainMessage();
       msg.what=2;
       msg.obj=mReader.readLine();
       handler.sendMessage(msg);
      }
      Thread.sleep(200);
     }
     mWriter.close();
     mReader.close();
     clientSocket.close();

可以看到在客户端通过while循环当mReader.ready()为true时就会读取服务器返回消息的一行,然后更新显示。
4、实现两个手机间的通讯服务器的实现

服务器端的代码我使用是MyEclipse,首先我们来看看上述发送消息的过程中服务器端运行的截图:

 

服务器端的功能是怎么实现的呢?毫无疑问首先要做的当然是初始化服务器并指定端口号,代码如下:

serverSocket = new ServerSocket(SOCKET_PORT);

接着当有客户端连接到服务器时会为每一个客户端开启一个子线程,并将这个子线程加入到集合中对应的代码如下

while (flag) {
    //有客户端连接,时serverSocket.accept()方法会返回客户端socket
    Socket clientSocket = serverSocket.accept();
    SocketThread socketThread = new SocketThread(clientSocket,socketId++);
    socketThread.start();
    mThreadList.add(socketThread);
   }

在开启的子线程SocketThread中会有一个while循环监听客户端发过来的消息,并将这条消息添加到mThreadList集合,在这个子线程中循环读取客户端发过来的消息  

//循环读取客户端发过来的消息
    while (flag) {
     if (reader.ready()) {
      String comeData=reader.readLine();
      JSONObject msgJson = new JSONObject(comeData);
      Message msg = new Message();
      msg.setTo(msgJson.getInt("to"));
      msg.setMsg(msgJson.getString("msg"));
      msg.setFrom(mSocketId); 
      msg.setTime(getTime(System.currentTimeMillis()));
      mMsgList.add(msg);
      System.out.println("用户:"+mSocketId+"向用户:"+msg.getTo()+"发送的消息内容为:"+msg.getMsg());
     }
     Thread.sleep(100);
    }

其实也就是说在服务器中为每一个连接到服务器的客户端开启一个子线程,并在这个子线程中循环监听这个客户端是否发过来消息,在上面我们看到服务器解析消息后,将这条消息封装到了Message这个bean中并添加到了集合中。Message中包含的信息从上面可以看出。到这里服务器就可以收到服务器发过来的消息了,服务器收到消息后要做的工作就是将这条消息发送给客户端,(从实现原理图中可以看出服务器起到一个中转的作用)那么怎样实现这个功能呢?它的实现也不难,从上面的描述我们可以知道只要客户端向服务器发送一条消息,我们就会将这条消息放到一个集合mMsgList中,也就是说只要服务器收到消息mMsgList这个集合就不为空,只要mMsgList这个集合不为空就说明服务器还拥有未转发的消息,需要转发。怎么实现转发呢?

      首先这里有两个集合一个是Message的集合mMsgList,另一个是为每一个客户端Socket开启的一个子线程SocketThread的集合mThreadList。这两个集合的关系是每一个Message肯定是mThreadList中的一个SocketThread(客户端)发送的。

当SocketThread的id与Messsage中的to(即消息的到达方)相等时,因为每一个客户端(假设是clientSocket1)连接到服务器时都要开启一个SocketThread子线程,在这个子线程中有clientSocket1的引用,所以当相等时就说明这个Message是发送给这个clientSocket1的。然后通过这个clientSocket1的BufferedWriter将这个消息发送给这个客户端。与其对应的代码如下

while(flag) {
      if(mMsgList.size() > 0) {
       Message from = mMsgList.get(0);
       for(SocketThread toThread : mThreadList) {
        //遍历mThreadList如果to.socketID==from.to说明这个toThread与mMsgList中的这条内容是对应的
        //这里toThread的作用是通过它得到这条消息的BufferedWriter,mMsgList.get(0)得到这条消息,然后通过
        //BufferedWriter将这条消息发送到指定方
        if(toThread.mSocketId == from.getTo()) {
         //这里的writer是SocketThread中的writer,这样才能保证在调用writer.flush之后消息到达
         //我们的指定方
         BufferedWriter writer = toThread.writer;
         JSONObject json = new JSONObject();
         json.put("from", from.getFrom());
         json.put("msg", from.getMsg());
         json.put("time", from.getTime());
         writer.write(json.toString()+"\n");
         writer.flush();
         System.out.println("转发消息成功");
         break;
        }
       }
       mMsgList.remove(0);
      }
      Thread.sleep(200);
     }

这样将这条消息解析封装成json后就发送到了指定的客户端,就完成了两个android机的通讯。其实个人觉着对这些原理的知识还是需要去好好学习,弄懂的,它的实现思想对我们以后的编程也是很有作用的。

关于实现两个手机端通讯的讨论就到这里了,可能我们看到的那些通讯的软件采用的方式不是本文使用的方式,但是原理性的东西是不会变的,这篇博客也是从最原始的地方来理解手机通讯的一些简单的原理。

如有谬误,欢迎批评指正,如有疑问欢迎留言。

如果本篇博客对你有帮助就点击左上角关注,关注吧,锁定本台观看更多精彩内容0.0

 

这里提醒大家注意的是源码包含两部分,一部分是服务端,另一部分是客户端,服务端是MyEclipse程序,客户端就是我们的android程序。

 
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页