【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代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    android:layout_weight="2"
    tools:context="jiugaosh.com.udpdemo.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="vertical"
        android:layout_weight="1">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="接收区:" />
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:textSize="8dp"
                android:id="@+id/btn_udpConn"
                android:text="建立连接" />
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:textSize="8dp"
                android:id="@+id/btn_udpClose"
                android:text="关闭连接" />
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="right"
                android:textSize="8dp"
                android:id="@+id/btn_CleanRecv"
                android:text="清除接收区" />
        </LinearLayout>

        <TextView
            android:layout_width="match_parent"
            android:layout_weight="7"
            android:layout_height="0dp"
            android:id="@+id/txt_Recv"
            android:background="@drawable/border"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:orientation="horizontal"
            android:layout_weight="2">
            <CheckBox
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="Hex显示"/>
            <CheckBox
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"

                android:text="二进制显示"/>
            <CheckBox
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="十进制显示"/>

        </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="vertical"
        android:layout_weight="1">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="发送区:" />
        <TextView
            android:layout_width="match_parent"
            android:layout_weight="7"
            android:background="@drawable/border"
            android:id="@+id/txt_Send"
            android:layout_height="0dp" />
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:orientation="horizontal"
            android:layout_weight="2">
            <CheckBox
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="Hex显示"/>
            <CheckBox
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"

                android:text="二进制显示"/>
            <CheckBox
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="十进制显示"/>

        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:orientation="horizontal"
            android:layout_weight="2">
            <EditText
                android:layout_width="0dp"
                android:layout_weight="5"
                android:id="@+id/edit_Send"
                android:background="@drawable/border"
                android:layout_height="match_parent" />
            <Button
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"
                android:layout_gravity="right"
                android:id="@+id/btn_Send"
                android:text="发送"/>
        </LinearLayout>
    </LinearLayout>
</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)


下面看具体代码实现:

package jiugaosh.com.udpdemo;

import android.content.Intent;
import android.util.Log;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

/**
 * Created by lenovo on 2016/2/23.
 */
public class UDPClient implements Runnable{
    final static int udpPort = 9999;
    final static String hostIp = "192.168.1.4";
    private static DatagramSocket socket = null;
    private static DatagramPacket packetSend,packetRcv;
    private boolean udpLife = true; //udp生命线程
    private byte[] msgRcv = new byte[1024]; //接收消息

    public UDPClient(){
        super();
    }

    //返回udp生命线程因子是否存活
    public boolean isUdpLife(){
        if (udpLife){
            return true;
        }

        return false;
    }

    //更改UDP生命线程因子
    public void setUdpLife(boolean b){
        udpLife = b;
    }

    //发送消息
    public String send(String msgSend){
        InetAddress hostAddress = null;

        try {
            hostAddress = InetAddress.getByName(hostIp);
        } catch (UnknownHostException e) {
            Log.i("udpClient","未找到服务器");
            e.printStackTrace();
        }

/*        try {
            socket = new DatagramSocket();
        } catch (SocketException e) {
            Log.i("udpClient","建立发送数据报失败");
            e.printStackTrace();
        }*/

         packetSend = new DatagramPacket(msgSend.getBytes() , msgSend.getBytes().length,hostAddress,udpPort);

        try {
            socket.send(packetSend);
        } catch (IOException e) {
            e.printStackTrace();
            Log.i("udpClient","发送失败");
        }
     //   socket.close();
        return msgSend;
    }

    @Override
    public void run() {

        try {
            socket = new DatagramSocket();
            socket.setSoTimeout(3000);//设置超时为3s
        } catch (SocketException e) {
            Log.i("udpClient","建立接收数据报失败");
            e.printStackTrace();
        }
        packetRcv = new DatagramPacket(msgRcv,msgRcv.length);
        while (udpLife){
            try {
                Log.i("udpClient", "UDP监听");
                socket.receive(packetRcv);
                String RcvMsg = new String(packetRcv.getData(),packetRcv.getOffset(),packetRcv.getLength());
                //将收到的消息发给主界面
                Intent RcvIntent = new Intent();
                RcvIntent.setAction("udpRcvMsg");
                RcvIntent.putExtra("udpRcvMsg", RcvMsg);
                MainActivity.context.sendBroadcast(RcvIntent);

                Log.i("Rcv",RcvMsg);
            }catch (IOException e){
                e.printStackTrace();
            }
        }

        Log.i("udpClient","UDP监听关闭");
        socket.close();
    }
}

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

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

MainActivity界面:

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

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

MyButtonClick类(处理各按钮事件)

BroadcastReceiver(广播接收器)

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


话不多说,放码过来:

package jiugaosh.com.udpdemo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.os.Handler;

import java.lang.ref.WeakReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class MainActivity extends AppCompatActivity {
    TextView txt_Recv,txt_Send;
    Button   btn_CleanRecv,btn_Send,btn_UdpConn,btn_UdpClose;
    EditText edit_Send;
    private UDPClient client = null;
    public static Context context;
    private final MyHandler myHandler = new MyHandler(this);
    private StringBuffer udpRcvStrBuf=new StringBuffer(),udpSendStrBuf=new StringBuffer();



    MyBtnClick myBtnClick = new MyBtnClick();


    private class MyHandler extends Handler{
        private final WeakReference<MainActivity> mActivity;
        public MyHandler(MainActivity activity){
            mActivity = new WeakReference<MainActivity>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    udpRcvStrBuf.append(msg.obj.toString());
                    txt_Recv.setText(udpRcvStrBuf.toString());
                    break;
                case 2:
                    udpSendStrBuf.append(msg.obj.toString());
                    txt_Send.setText(udpSendStrBuf.toString());
                    break;
                case 3:
                    txt_Recv.setText(udpRcvStrBuf.toString());
                    break;
            }
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        bindWidget();   //控件绑定
        listening();    //监听事件
        bindReceiver();//注册broadcastReceiver接收器
        iniWidget();    //初始化控件状态
    }

    private void bindWidget(){
        txt_Recv = (TextView)findViewById(R.id.txt_Recv);
        txt_Send = (TextView)findViewById(R.id.txt_Send);
        btn_CleanRecv = (Button)findViewById(R.id.btn_CleanRecv);
        btn_Send = (Button)findViewById(R.id.btn_Send);
        btn_UdpConn = (Button)findViewById(R.id.btn_udpConn);
        btn_UdpClose = (Button)findViewById(R.id.btn_udpClose);
        edit_Send = (EditText)findViewById(R.id.edit_Send);
    }

    private void listening(){
        btn_Send.setOnClickListener(myBtnClick);
        btn_UdpConn.setOnClickListener(myBtnClick);
        btn_UdpClose.setOnClickListener(myBtnClick);
        btn_CleanRecv.setOnClickListener(myBtnClick);
    }

    private void bindReceiver(){
        IntentFilter udpRcvIntentFilter = new IntentFilter("udpRcvMsg");
        registerReceiver(broadcastReceiver,udpRcvIntentFilter);
    }

    private void iniWidget(){
        btn_Send.setEnabled(false);
    }

    class MyBtnClick implements Button.OnClickListener{

        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.btn_CleanRecv:
                    udpRcvStrBuf.delete(0,udpRcvStrBuf.length());
                    Message message = new Message();
                    message.what = 3;
                    myHandler.sendMessage(message);
                    break;
                case R.id.btn_udpConn:
                    //建立线程池
                    ExecutorService exec = Executors.newCachedThreadPool();
                    client = new UDPClient();
                    exec.execute(client);
                    btn_UdpClose.setEnabled(true);
                    btn_UdpConn.setEnabled(false);
                    btn_Send.setEnabled(true);
                    break;
                case R.id.btn_udpClose:
                    client.setUdpLife(false);
                    btn_UdpConn.setEnabled(true);
                    btn_UdpClose.setEnabled(false);
                    btn_Send.setEnabled(false);
                    break;
                case R.id.btn_Send:
                    Thread thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            Message message = new Message();
                            message.what = 2;
                            if (edit_Send.getText().toString()!=""){
                                client.send(edit_Send.getText().toString());
                                message.obj = edit_Send.getText().toString();
                                myHandler.sendMessage(message);
                            }
                            
                        }
                    });
                    thread.start();
                    break;
            }
        }
    }

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.hasExtra("udpRcvMsg"))  {
                Message message = new Message();
                message.obj = intent.getStringExtra("udpRcvMsg");
                message.what = 1;
                Log.i("主界面Broadcast","收到"+message.obj.toString());
                myHandler.sendMessage(message);
            }
        }
    };


}
当然,不能忘记在AndroidMainFest文件中加上权限,毕竟你是要联网的!
<uses-permission android:name="android.permission.INTERNET" />


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


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


附上demo:

http://download.csdn.net/detail/shankezh/9442049


  • 7
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值