Rosmin--两台Android手机的Socket双向通信

转自:http://blog.csdn.net/f_season/article/details/9170617

 上学期搞定了小车,现在终于结束了大机器人,趁还没真正进入考研复习的高潮赶紧把以前的代码整理整理。

       先讲讲我们那小车,2台手机+车体组成。一个手机放车上作为server,用其摄像头、陀螺仪、磁力计来获取图像、确定小车方向。另一台手机负责控制,作为client,并画出小车行进图。如何从server获取陀螺仪、磁力计角度,又如何把client的控制命令发送给server就成了一个问题。这里我们使用socket双向通信。

       先讲client部分

[java]  view plain copy
  1.  // Socket Client connect to Server  
  2.     connectButton.setOnClickListener(new Button.OnClickListener()  
  3.     {  
  4.       @Override  
  5.       public void onClick(View v)  
  6.       {  
  7.         // TODO Auto-generated method stub  
  8.         try  
  9.         {  
  10.           ip = mEditText02.getText().toString();  
  11.           Thread thread = new Thread(new mSocketConnectRunnable2());  
  12.           thread.start();  
  13. //          thread.sleep(100);  
  14.           goToControl();           //进行控制命令的处理  
  15.           connectButton.setVisibility(View.INVISIBLE);  
  16.           mEditText02.setVisibility(View.INVISIBLE);  
  17.         }  
  18.         catch (Exception e)   
  19.         {  
  20.           e.printStackTrace();  
  21.         }  
  22.       }  
  23.     });    

      两台手机都连接到同个wifi,这个就不多讲了。首先你得有个EditText填写server的IP地址,然后有个按钮,点击启动个线程,负责与server通信,这里传给Thread的构造函数调用Runnable接口。socket其实就是对某一个服务器的一个端口进行连接,连接上后就形成会话。由于这里socket是全双向的字节流,所以连上的时候其本身就已经具备了双向通信能力。

      然后我们看它调用的接口,怎么连接和接受server发来的数据……

[java]  view plain copy
  1. //Socket Client  
  2.  public class mSocketConnectRunnable2 implements Runnable  
  3.  {           
  4.    @Override  
  5.    public void run()  
  6.    {  
  7.      try  
  8.      {  
  9.     mSocket02 = new Socket(ip, intSocketServerPort);  
  10.     if(mSocket02.isConnected())  
  11.        {  
  12.          Log.i(TAG, "Socket Client is connected to Server.");  
  13.          strTemp01="Socket Client is connected to Server.";         
  14.        }  
  15.        BufferedReader br = new BufferedReader(new InputStreamReader(mSocket02.getInputStream()));  
  16.        while (true)  
  17.        {  
  18.         strTemp01 = br.readLine();  
  19.         if(!strTemp01.isEmpty())  
  20.           handler.post(rReceiveInfo);             
  21.        }  
  22.      }  
  23.      catch(Exception e)  
  24.      {  
  25.        if(bIfDebug)  
  26.        {  
  27.          Log.e(TAG, e.toString());  
  28.          e.printStackTrace();  
  29.        }  
  30.      }  
  31.    }  
  32.  }  

         ip上面说了,intSocketServerPort是socket端口,我这里设置为8080。mSocket02就像个水管,可以往里灌水也可以抽水。这里通过BufferedReader获得字节流,用handler传递进行数据处理。这里推荐用handler,不仅增加代码可度性,更容易避免莫名其妙的bug……

        以上是建立socket连接并且从server获取字节流的过程,下面是发送字节流的部分……

[java]  view plain copy
  1. public static void action(String a){  
  2.     //当Socket连接正常且不为空时,流输出给server  
  3.     if(mSocket02!=null && mSocket02.isConnected() && !a.equals(""))  
  4.     {   
  5.       try  
  6.       {               
  7.         bw = new BufferedWriter(new OutputStreamWriter(mSocket02.getOutputStream()));            
  8.         bw.write(a+"\n");  
  9.         bw.flush();           
  10.       }  
  11.       catch (Exception e)  
  12.       {  
  13.           Log.e(TAG, e.toString());  
  14.           e.printStackTrace();  
  15.         }  
  16.     }  
  17.   }  

         这里,比如我用 action("forward"),则字节流将forward发往server,至于这里流输出,不过多解释,详细的需要自己仔细查看socket。


         然后是server部分……这里我们设置一个按钮用于开启socket server

[java]  view plain copy
  1. // Run Socket Server  
  2.     mButton01.setOnClickListener(new Button.OnClickListener()  
  3.     {  
  4.       @Override  
  5.       public void onClick(View v)  
  6.       {  
  7.         // TODO Auto-generated method stub  
  8.         mButton01.setEnabled(false);  
  9.         mButton02.setEnabled(true);  
  10.         setContentView(R.layout.i3);  
  11.         Thread thread = new Thread(new mSocketConnectRunnable1());  
  12.         thread.start();  
  13.       }  
  14.     });  


         这里也是用Thread的构造函数调用Runnable接口

[java]  view plain copy
  1. //Socket Server  
  2.  public class mSocketConnectRunnable1 implements Runnable  
  3.  {  
  4.    @Override  
  5.    public void run()  
  6.    {  
  7.      // TODO Auto-generated method stub  
  8.      try  
  9.      {  
  10.        mServerSocket01 = new ServerSocket(intSocketServerPort);  
  11.        mServerSocket01.setReuseAddress(true);  
  12.        Log.i(TAG, strDebugPreFix+"Socket Server is Running: "+intSocketServerPort);  
  13.   
  14.        while (!mServerSocket01.isClosed())  
  15.        {    
  16.          mSocket01 = mServerSocket01.accept();  
  17.          Thread read = new Thread(new Runnable()  
  18.          {  
  19.            BufferedReader br = new BufferedReader(new InputStreamReader(mSocket01.getInputStream()));   
  20.            @Override  
  21.            public void run()  
  22.            {  
  23.              try  
  24.              {                               
  25.                while (mSocket01.isConnected())  
  26.                {                    
  27.                  msg = br.readLine();  
  28.                  Handler01.post(rManualControl);  
  29.                }  
  30.              }  
  31.              catch (Exception e)  
  32.              {  
  33.                if(bIfDebug)  
  34.                {  
  35.                  Log.e(TAG, e.toString());  
  36.                  e.printStackTrace();  
  37.                }  
  38.              }              
  39.            }  
  40.          });  
  41.          read.start();         
  42.          
  43.          //在接受数据的同时发送数据,实现双向通信  
  44.        Thread write = new Thread (new Runnable()  
  45.        {  
  46.          @Override  
  47.          public void run()  
  48.          {  
  49.            while (mSocket01.isConnected())  
  50.            {  
  51.              try  
  52.              {  
  53.                Thread.sleep(100);  
  54.              }  
  55.              catch (InterruptedException e)  
  56.              {  
  57.                // TODO Auto-generated catch block  
  58.                e.printStackTrace();  
  59.              }  
  60.              Handler01.post(rSendStr);  
  61.            }  
  62.          }  
  63.        });  
  64.         write.start();  
  65.        }  
  66.      }     
  67.      catch(Exception e)  
  68.      {  
  69.        if(bIfDebug)  
  70.        {  
  71.          Log.e(TAG, e.toString());  
  72.          e.printStackTrace();  
  73.        }  
  74.      }  
  75.    }  
  76.  }    
 
[java]  view plain copy
  1. public Runnable rSendStr = new Runnable(){  
  2.     public void run()  
  3.     {  
  4.       try  
  5.       {  
  6.         BufferedWriter bw = new BufferedWriter( new OutputStreamWriter(mSocket01.getOutputStream()) );  
  7.         strMove = strMoveFlag  
  8.         + " "  + String.valueOf((int) gyrAngle)   
  9.         + " " + String.valueOf( ( ((int)corrected_a) +((accX>3)?90:180) )%360)    //由于小车姿态问题,需要进行修正  
  10.         + " " + strQR  
  11.         +" \n";  
  12.         bw.write(strMove);  
  13.         bw.flush();  
  14.         strQR = "0"// accX>3   
  15.       }  
  16.       catch (IOException e)  
  17.       {  
  18.         // TODO Auto-generated catch block  
  19.         e.printStackTrace();  
  20.       }    
  21.     }  
  22.   };  

    这里用了read write两个thread,分别负责流输入和流输出。这里唯独要提的就是write部分,加上sleep控制流输出频率,不然会造成堵塞。将BufferedWriter通过handler放到Runnable中解决莫名其妙的问题(我的基础不行……惭愧惭愧……)。

PS:用handler解决部分问题,多亏了队友sununs11.这里是我们组项目中截下的代码,会有很多无关于本文双向通信的代码,请无视……后续会放出全部代码与代码解释……这代码是干什么的???请看这个简短视频:基于OpenCV和Android的语音物标识别车


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值