【Android Socket专题】:UDP通信客户端app的demo的实现

Android Socket 专题:

UDP Client客户端  http://blog.csdn.net/shankezh/article/details/50731287

UDP Server服务器 http://blog.csdn.net/shankezh/article/details/51452811

TCP Client客户端  http://blog.csdn.net/shankezh/article/details/70763579

TCP Server服务器 http://blog.csdn.net/shankezh/article/details/51555455

关于UDP通信其实可以不用多做累述,多数像我一样的朋友在此基础上也只是为了应用,需要了解下该了解的就可以了,具体的想要对这个协议研究深入的,可以自己努力!我这儿只做Android客户端的应用实现,注意是客户端,不是服务器,那么服务器怎么实现呢? 点击上方,已经补充!!!


规划自己的界面的(非常简单):

XML实现效果图如下:

附上对应XML代码:

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:paddingBottom="@dimen/activity_vertical_margin"  
  7.     android:paddingLeft="@dimen/activity_horizontal_margin"  
  8.     android:paddingRight="@dimen/activity_horizontal_margin"  
  9.     android:paddingTop="@dimen/activity_vertical_margin"  
  10.     android:orientation="vertical"  
  11.     android:layout_weight="2"  
  12.     tools:context="jiugaosh.com.udpdemo.MainActivity">  
  13.   
  14.     <LinearLayout  
  15.         android:layout_width="match_parent"  
  16.         android:layout_height="0dp"  
  17.         android:orientation="vertical"  
  18.         android:layout_weight="1">  
  19.         <LinearLayout  
  20.             android:layout_width="match_parent"  
  21.             android:layout_height="0dp"  
  22.             android:layout_weight="1">  
  23.             <TextView  
  24.                 android:layout_width="wrap_content"  
  25.                 android:layout_height="wrap_content"  
  26.                 android:layout_weight="1"  
  27.                 android:text="接收区:" />  
  28.             <Button  
  29.                 android:layout_width="wrap_content"  
  30.                 android:layout_height="wrap_content"  
  31.                 android:layout_gravity="right"  
  32.                 android:textSize="8dp"  
  33.                 android:id="@+id/btn_udpConn"  
  34.                 android:text="建立连接" />  
  35.             <Button  
  36.                 android:layout_width="wrap_content"  
  37.                 android:layout_height="wrap_content"  
  38.                 android:layout_gravity="right"  
  39.                 android:textSize="8dp"  
  40.                 android:id="@+id/btn_udpClose"  
  41.                 android:text="关闭连接" />  
  42.             <Button  
  43.                 android:layout_width="wrap_content"  
  44.                 android:layout_height="wrap_content"  
  45.                 android:layout_gravity="right"  
  46.                 android:textSize="8dp"  
  47.                 android:id="@+id/btn_CleanRecv"  
  48.                 android:text="清除接收区" />  
  49.         </LinearLayout>  
  50.   
  51.         <TextView  
  52.             android:layout_width="match_parent"  
  53.             android:layout_weight="7"  
  54.             android:layout_height="0dp"  
  55.             android:id="@+id/txt_Recv"  
  56.             android:background="@drawable/border"/>  
  57.         <LinearLayout  
  58.             android:layout_width="match_parent"  
  59.             android:layout_height="0dp"  
  60.             android:orientation="horizontal"  
  61.             android:layout_weight="2">  
  62.             <CheckBox  
  63.                 android:layout_width="0dp"  
  64.                 android:layout_height="wrap_content"  
  65.                 android:layout_weight="2"  
  66.                 android:text="Hex显示"/>  
  67.             <CheckBox  
  68.                 android:layout_width="0dp"  
  69.                 android:layout_height="wrap_content"  
  70.                 android:layout_weight="2"  
  71.   
  72.                 android:text="二进制显示"/>  
  73.             <CheckBox  
  74.                 android:layout_width="0dp"  
  75.                 android:layout_height="wrap_content"  
  76.                 android:layout_weight="2"  
  77.                 android:text="十进制显示"/>  
  78.   
  79.         </LinearLayout>  
  80.   
  81.     </LinearLayout>  
  82.   
  83.     <LinearLayout  
  84.         android:layout_width="match_parent"  
  85.         android:layout_height="0dp"  
  86.         android:orientation="vertical"  
  87.         android:layout_weight="1">  
  88.         <TextView  
  89.             android:layout_width="wrap_content"  
  90.             android:layout_height="0dp"  
  91.             android:layout_weight="1"  
  92.             android:text="发送区:" />  
  93.         <TextView  
  94.             android:layout_width="match_parent"  
  95.             android:layout_weight="7"  
  96.             android:background="@drawable/border"  
  97.             android:id="@+id/txt_Send"  
  98.             android:layout_height="0dp" />  
  99.         <LinearLayout  
  100.             android:layout_width="match_parent"  
  101.             android:layout_height="0dp"  
  102.             android:orientation="horizontal"  
  103.             android:layout_weight="2">  
  104.             <CheckBox  
  105.                 android:layout_width="0dp"  
  106.                 android:layout_height="wrap_content"  
  107.                 android:layout_weight="2"  
  108.                 android:text="Hex显示"/>  
  109.             <CheckBox  
  110.                 android:layout_width="0dp"  
  111.                 android:layout_height="wrap_content"  
  112.                 android:layout_weight="2"  
  113.   
  114.                 android:text="二进制显示"/>  
  115.             <CheckBox  
  116.                 android:layout_width="0dp"  
  117.                 android:layout_height="wrap_content"  
  118.                 android:layout_weight="2"  
  119.                 android:text="十进制显示"/>  
  120.   
  121.         </LinearLayout>  
  122.         <LinearLayout  
  123.             android:layout_width="match_parent"  
  124.             android:layout_height="0dp"  
  125.             android:orientation="horizontal"  
  126.             android:layout_weight="2">  
  127.             <EditText  
  128.                 android:layout_width="0dp"  
  129.                 android:layout_weight="5"  
  130.                 android:id="@+id/edit_Send"  
  131.                 android:background="@drawable/border"  
  132.                 android:layout_height="match_parent" />  
  133.             <Button  
  134.                 android:layout_width="0dp"  
  135.                 android:layout_weight="1"  
  136.                 android:layout_height="match_parent"  
  137.                 android:layout_gravity="right"  
  138.                 android:id="@+id/btn_Send"  
  139.                 android:text="发送"/>  
  140.         </LinearLayout>  
  141.     </LinearLayout>  
  142. </LinearLayout>  

至此我们界面全部完成,我们开始实现对应功能!继续向下看。

首先在写代码前要说明下关键性的几个类,我们完成udp客户端其实主要就是通过这几个类实现的:

1、DatagramSocket

2、DatagramPacket 

3、InetAddress

关于这几个类到底是什么意思,包含了什么信息,大家可以自己去百度谷歌,或者直接打开JAVA API文档查看便知,这里不做赘述,看具体实现。

关于UDP客户端收发这里,实现思路是:

启动UDP线程:

1、创建DatagramSocket通信数据报

2、建立接收事件专用DatagramPacket数据包

3、创建超时(这个和后面关闭通信有关)

4、建立监听接收消息循环机制(接收消息处理在此处,接收到的消息通过BroadcastReceiver发送给主界面)

5、结束循环,关闭数据报。

以上为收取信息思路,发送信息则为UDP线程中的一个方法,直接被调用,共享了接收块的DatagramSocket数据报:

UDP Thread Run--->[Function方法]send(String SendMsg)


下面看具体代码实现:

[java]  view plain  copy
  1. package jiugaosh.com.udpdemo;  
  2.   
  3. import android.content.Intent;  
  4. import android.util.Log;  
  5.   
  6. import java.io.IOException;  
  7. import java.net.DatagramPacket;  
  8. import java.net.DatagramSocket;  
  9. import java.net.InetAddress;  
  10. import java.net.SocketException;  
  11. import java.net.UnknownHostException;  
  12.   
  13. /** 
  14.  * Created by lenovo on 2016/2/23. 
  15.  */  
  16. public class UDPClient implements Runnable{  
  17.     final static int udpPort = 9999;  
  18.     final static String hostIp = "192.168.1.4";  
  19.     private static DatagramSocket socket = null;  
  20.     private static DatagramPacket packetSend,packetRcv;  
  21.     private boolean udpLife = true//udp生命线程  
  22.     private byte[] msgRcv = new byte[1024]; //接收消息  
  23.   
  24.     public UDPClient(){  
  25.         super();  
  26.     }  
  27.   
  28.     //返回udp生命线程因子是否存活  
  29.     public boolean isUdpLife(){  
  30.         if (udpLife){  
  31.             return true;  
  32.         }  
  33.   
  34.         return false;  
  35.     }  
  36.   
  37.     //更改UDP生命线程因子  
  38.     public void setUdpLife(boolean b){  
  39.         udpLife = b;  
  40.     }  
  41.   
  42.     //发送消息  
  43.     public String send(String msgSend){  
  44.         InetAddress hostAddress = null;  
  45.   
  46.         try {  
  47.             hostAddress = InetAddress.getByName(hostIp);  
  48.         } catch (UnknownHostException e) {  
  49.             Log.i("udpClient","未找到服务器");  
  50.             e.printStackTrace();  
  51.         }  
  52.   
  53. /*        try { 
  54.             socket = new DatagramSocket(); 
  55.         } catch (SocketException e) { 
  56.             Log.i("udpClient","建立发送数据报失败"); 
  57.             e.printStackTrace(); 
  58.         }*/  
  59.   
  60.          packetSend = new DatagramPacket(msgSend.getBytes() , msgSend.getBytes().length,hostAddress,udpPort);  
  61.   
  62.         try {  
  63.             socket.send(packetSend);  
  64.         } catch (IOException e) {  
  65.             e.printStackTrace();  
  66.             Log.i("udpClient","发送失败");  
  67.         }  
  68.      //   socket.close();  
  69.         return msgSend;  
  70.     }  
  71.   
  72.     @Override  
  73.     public void run() {  
  74.   
  75.         try {  
  76.             socket = new DatagramSocket();  
  77.             socket.setSoTimeout(3000);//设置超时为3s  
  78.         } catch (SocketException e) {  
  79.             Log.i("udpClient","建立接收数据报失败");  
  80.             e.printStackTrace();  
  81.         }  
  82.         packetRcv = new DatagramPacket(msgRcv,msgRcv.length);  
  83.         while (udpLife){  
  84.             try {  
  85.                 Log.i("udpClient""UDP监听");  
  86.                 socket.receive(packetRcv);  
  87.                 String RcvMsg = new String(packetRcv.getData(),packetRcv.getOffset(),packetRcv.getLength());  
  88.                 //将收到的消息发给主界面  
  89.                 Intent RcvIntent = new Intent();  
  90.                 RcvIntent.setAction("udpRcvMsg");  
  91.                 RcvIntent.putExtra("udpRcvMsg", RcvMsg);  
  92.                 MainActivity.context.sendBroadcast(RcvIntent);  
  93.   
  94.                 Log.i("Rcv",RcvMsg);  
  95.             }catch (IOException e){  
  96.                 e.printStackTrace();  
  97.             }  
  98.         }  
  99.   
  100.         Log.i("udpClient","UDP监听关闭");  
  101.         socket.close();  
  102.     }  
  103. }  

至此UDP核心代码全部部署完成,其中包含了少许其他功能, 如发送给主界面消息代码等,不影响,有不需要的可以自行删除。其中如果想发送消息,那么调用其中的send方法即可。

下面则是主界面代码实现,我的实现思路如下(各有各的实现方法,如果您有更好的,如果愿意请告诉我,我十分愿意学习):

MainActivity界面:

Handler类(主要处理UI更新事件)

OnCreate(绑定控件,事件监听,注册BroadcastReceiver等)

MyButtonClick类(处理各按钮事件)

BroadcastReceiver(广播接收器)

至于里面各自类包含的小逻辑,就不多讲了,看demo可以很快便知道如何使用对应了。


话不多说,放码过来:

[java]  view plain  copy
  1. package jiugaosh.com.udpdemo;  
  2.   
  3. import android.content.BroadcastReceiver;  
  4. import android.content.Context;  
  5. import android.content.Intent;  
  6. import android.content.IntentFilter;  
  7. import android.os.Message;  
  8. import android.support.v7.app.AppCompatActivity;  
  9. import android.os.Bundle;  
  10. import android.util.Log;  
  11. import android.view.View;  
  12. import android.widget.Button;  
  13. import android.widget.EditText;  
  14. import android.widget.TextView;  
  15. import android.os.Handler;  
  16.   
  17. import java.lang.ref.WeakReference;  
  18. import java.util.concurrent.ExecutorService;  
  19. import java.util.concurrent.Executors;  
  20.   
  21.   
  22. public class MainActivity extends AppCompatActivity {  
  23.     TextView txt_Recv,txt_Send;  
  24.     Button   btn_CleanRecv,btn_Send,btn_UdpConn,btn_UdpClose;  
  25.     EditText edit_Send;  
  26.     private UDPClient client = null;  
  27.     public static Context context;  
  28.     private final MyHandler myHandler = new MyHandler(this);  
  29.     private StringBuffer udpRcvStrBuf=new StringBuffer(),udpSendStrBuf=new StringBuffer();  
  30.   
  31.   
  32.   
  33.     MyBtnClick myBtnClick = new MyBtnClick();  
  34.   
  35.   
  36.     private class MyHandler extends Handler{  
  37.         private final WeakReference<MainActivity> mActivity;  
  38.         public MyHandler(MainActivity activity){  
  39.             mActivity = new WeakReference<MainActivity>(activity);  
  40.         }  
  41.         @Override  
  42.         public void handleMessage(Message msg) {  
  43.             super.handleMessage(msg);  
  44.             switch (msg.what){  
  45.                 case 1:  
  46.                     udpRcvStrBuf.append(msg.obj.toString());  
  47.                     txt_Recv.setText(udpRcvStrBuf.toString());  
  48.                     break;  
  49.                 case 2:  
  50.                     udpSendStrBuf.append(msg.obj.toString());  
  51.                     txt_Send.setText(udpSendStrBuf.toString());  
  52.                     break;  
  53.                 case 3:  
  54.                     txt_Recv.setText(udpRcvStrBuf.toString());  
  55.                     break;  
  56.             }  
  57.         }  
  58.     }  
  59.   
  60.   
  61.     @Override  
  62.     protected void onCreate(Bundle savedInstanceState) {  
  63.         super.onCreate(savedInstanceState);  
  64.         setContentView(R.layout.activity_main);  
  65.         context = this;  
  66.         bindWidget();   //控件绑定  
  67.         listening();    //监听事件  
  68.         bindReceiver();//注册broadcastReceiver接收器  
  69.         iniWidget();    //初始化控件状态  
  70.     }  
  71.   
  72.     private void bindWidget(){  
  73.         txt_Recv = (TextView)findViewById(R.id.txt_Recv);  
  74.         txt_Send = (TextView)findViewById(R.id.txt_Send);  
  75.         btn_CleanRecv = (Button)findViewById(R.id.btn_CleanRecv);  
  76.         btn_Send = (Button)findViewById(R.id.btn_Send);  
  77.         btn_UdpConn = (Button)findViewById(R.id.btn_udpConn);  
  78.         btn_UdpClose = (Button)findViewById(R.id.btn_udpClose);  
  79.         edit_Send = (EditText)findViewById(R.id.edit_Send);  
  80.     }  
  81.   
  82.     private void listening(){  
  83.         btn_Send.setOnClickListener(myBtnClick);  
  84.         btn_UdpConn.setOnClickListener(myBtnClick);  
  85.         btn_UdpClose.setOnClickListener(myBtnClick);  
  86.         btn_CleanRecv.setOnClickListener(myBtnClick);  
  87.     }  
  88.   
  89.     private void bindReceiver(){  
  90.         IntentFilter udpRcvIntentFilter = new IntentFilter("udpRcvMsg");  
  91.         registerReceiver(broadcastReceiver,udpRcvIntentFilter);  
  92.     }  
  93.   
  94.     private void iniWidget(){  
  95.         btn_Send.setEnabled(false);  
  96.     }  
  97.   
  98.     class MyBtnClick implements Button.OnClickListener{  
  99.   
  100.         @Override  
  101.         public void onClick(View v) {  
  102.             switch (v.getId()){  
  103.                 case R.id.btn_CleanRecv:  
  104.                     udpRcvStrBuf.delete(0,udpRcvStrBuf.length());  
  105.                     Message message = new Message();  
  106.                     message.what = 3;  
  107.                     myHandler.sendMessage(message);  
  108.                     break;  
  109.                 case R.id.btn_udpConn:  
  110.                     //建立线程池  
  111.                     ExecutorService exec = Executors.newCachedThreadPool();  
  112.                     client = new UDPClient();  
  113.                     exec.execute(client);  
  114.                     btn_UdpClose.setEnabled(true);  
  115.                     btn_UdpConn.setEnabled(false);  
  116.                     btn_Send.setEnabled(true);  
  117.                     break;  
  118.                 case R.id.btn_udpClose:  
  119.                     client.setUdpLife(false);  
  120.                     btn_UdpConn.setEnabled(true);  
  121.                     btn_UdpClose.setEnabled(false);  
  122.                     btn_Send.setEnabled(false);  
  123.                     break;  
  124.                 case R.id.btn_Send:  
  125.                     Thread thread = new Thread(new Runnable() {  
  126.                         @Override  
  127.                         public void run() {  
  128.                             Message message = new Message();  
  129.                             message.what = 2;  
  130.                             if (edit_Send.getText().toString()!=""){  
  131.                                 client.send(edit_Send.getText().toString());  
  132.                                 message.obj = edit_Send.getText().toString();  
  133.                                 myHandler.sendMessage(message);  
  134.                             }  
  135.                               
  136.                         }  
  137.                     });  
  138.                     thread.start();  
  139.                     break;  
  140.             }  
  141.         }  
  142.     }  
  143.   
  144.     private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {  
  145.         @Override  
  146.         public void onReceive(Context context, Intent intent) {  
  147.             if (intent.hasExtra("udpRcvMsg"))  {  
  148.                 Message message = new Message();  
  149.                 message.obj = intent.getStringExtra("udpRcvMsg");  
  150.                 message.what = 1;  
  151.                 Log.i("主界面Broadcast","收到"+message.obj.toString());  
  152.                 myHandler.sendMessage(message);  
  153.             }  
  154.         }  
  155.     };  
  156.   
  157.   
  158. }  
当然,不能忘记在AndroidMainFest文件中加上权限,毕竟你是要联网的!
[html]  view plain  copy
  1. <uses-permission android:name="android.permission.INTERNET" />  


写在最后:实现这些功能其实较为简单,网上有很多成熟且很棒的例子,各位多看多学,必没有问题!其中进制转换其实很简单实现,各位只要对那两个stringbuffer进行进制操作和显示即可!


通信效果请点击上方UDP server最后有图片展示

猜你喜欢

转载自blog.csdn.net/lpcrazyboy/article/details/80304876