【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
    评论
好的,下面我会分别给您提供 Java 实现Socket 服务器和 Android Socket 客户端示例代码。 Java 实现Socket 服务器 ```java import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class SocketServer { public static void main(String[] args) throws IOException { // 创建一个 ServerSocket,监听指定端口 ServerSocket serverSocket = new ServerSocket(8888); System.out.println("Socket 服务器已启动,等待客户端连接..."); // 等待客户端连接 Socket socket = serverSocket.accept(); System.out.println("客户端已连接:" + socket.getInetAddress().getHostAddress()); // 获取输入流和输出流 InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); // 读取客户端发送的数据 byte[] buffer = new byte[1024]; int len = inputStream.read(buffer); String message = new String(buffer, 0, len); System.out.println("收到客户端消息:" + message); // 发送响应数据给客户端 String response = "Hello, Client!"; outputStream.write(response.getBytes()); // 关闭资源 outputStream.close(); inputStream.close(); socket.close(); serverSocket.close(); System.out.println("Socket 服务器已关闭"); } } ``` Android Socket 客户端示例代码 ```java import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private static final String TAG = "MainActivity"; private EditText mEtServerIp; private EditText mEtServerPort; private EditText mEtMessage; private Button mBtnSend; private TextView mTvResponse; private Socket mSocket; private InputStream mInputStream; private OutputStream mOutputStream; private static final int MSG_RECEIVED = 1; private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_RECEIVED: String message = (String) msg.obj; mTvResponse.setText(message); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mEtServerIp = findViewById(R.id.et_server_ip); mEtServerPort = findViewById(R.id.et_server_port); mEtMessage = findViewById(R.id.et_message); mBtnSend = findViewById(R.id.btn_send); mTvResponse = findViewById(R.id.tv_response); mBtnSend.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_send: new Thread(new Runnable() { @Override public void run() { try { // 获取服务端 IP 和端口号 String serverIp = mEtServerIp.getText().toString().trim(); int serverPort = Integer.parseInt(mEtServerPort.getText().toString().trim()); // 创建 Socket 连接 mSocket = new Socket(serverIp, serverPort); // 获取输入流和输出流 mInputStream = mSocket.getInputStream(); mOutputStream = mSocket.getOutputStream(); // 发送消息给服务端 String message = mEtMessage.getText().toString().trim(); mOutputStream.write(message.getBytes()); // 读取服务端响应消息 byte[] buffer = new byte[1024]; int len = mInputStream.read(buffer); String response = new String(buffer, 0, len); // 发送消息给主线程更新 UI Message msg = mHandler.obtainMessage(MSG_RECEIVED, response); mHandler.sendMessage(msg); } catch (IOException e) { e.printStackTrace(); } finally { try { if (mSocket != null) { mSocket.close(); } if (mOutputStream != null) { mOutputStream.close(); } if (mInputStream != null) { mInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } } }).start(); break; } } } ``` 以上代码仅供参考,具体实现要根据您的需求和具体情况进行调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值