Android之UDP协议通讯

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

最近在做的项目中用到了UDP协议来通讯,整理了一下,可以与PC端网络助手之间进行测试。下面将主要功能代码写在下面供搭建参考:
UDPSocketClientManage

public class UDPSocketClientManage {

    // 服务器IP

    private static String SERVER_IP = "192.168.1.68";

    // 服务器端口

    private static int LOCAL_PORT_AUDIO = 10000;

    // 接收数据包

    private DatagramPacket Packet_Receive;

    // 端口

    private DatagramSocket msocketClient;



    NetworkState mLastNetworkState = NetworkState.NETWORK_STATE_NULL;

    SocketConnectListener mConnectListener = null;



    // 设置网络连接参数

    public void setNetworkParameter(String strIP, int nPort) {

        SERVER_IP = strIP;

        LOCAL_PORT_AUDIO = nPort;

    }



    // 注册接收连接状态和数据的回调函数

    public void RegSocketConnectListener(SocketConnectListener listener) {

        mConnectListener = listener;

    }



    /**

     * 启动连接服务器

     */

    public void Connect() {

        // 正在开始连接

        mLastNetworkState = NetworkState.NETWORK_STATE_CONNECT_ING;



        try {

            // 端口

            msocketClient = new DatagramSocket(LOCAL_PORT_AUDIO);

            // 接收数据缓存

            byte[] Buffer_Receive = new byte[1024];

            // 接收包

            Packet_Receive = new DatagramPacket(Buffer_Receive, 1024);



            mLastNetworkState = NetworkState.NETWORK_STATE_CONNECT_SUCCEED;



        } catch (IOException e) {

            mLastNetworkState = NetworkState.NETWORK_STATE_CONNECT_FAILLD;

            Log.e("Show", e.toString());

            e.printStackTrace();

        } catch (Exception e) {

            mLastNetworkState = NetworkState.NETWORK_STATE_CONNECT_FAILLD;

            Log.e("Show", e.toString());

            e.printStackTrace();

        }



        // 向回调发数据

        if (null != mConnectListener) {

            mConnectListener.OnConnectStatusCallBack(mLastNetworkState);

        }



        if (msocketClient != null) {

            new Thread(reRunnable).start();

        }

    }



    Runnable reRunnable = new Runnable() {

        @SuppressLint("NewApi")

        @Override

        public void run() {

            while (true) {

                try {

                    // 接收数据

                    if (Packet_Receive != null) {

                        msocketClient.receive(Packet_Receive);



                        // 判断数据是否合法

                        InetSocketAddress address = (InetSocketAddress) Packet_Receive.getSocketAddress();

                        // 判断是否是调度服务器的ip

                        if (!address.getHostName().equals(SERVER_IP)) {

                            continue;

                        }

                        // 判断是否是调度服务器的端口

                        if (address.getPort() != LOCAL_PORT_AUDIO) {

                            continue;

                        }



                        int length = Packet_Receive.getLength();

                        if (length > 0)

                            mConnectListener.OnReceiverCallBack(length, Packet_Receive.getData());

                    }



                } catch (IOException e) {

                    e.printStackTrace();

                    Log.e("Show", e.toString());

                }

            }

        }

    };



    /**

     * 断开连接

     */

    public void Close() {

        if (msocketClient != null) {

            msocketClient = null;

            mLastNetworkState = NetworkState.NETWORK_STATE_DISCONNECT_SUCCEED;

            mConnectListener.OnConnectStatusCallBack(mLastNetworkState);

        }

    }



    /**

     * @param data :需要发送的数据

     * @param len  :数据字节数据

     * @brief 发送数据

     */

    public void send(byte[] data, int len) {

        Thread_Send thread_send = new Thread_Send(data, len);

        new Thread(thread_send).start();

    }



    /**

     * @brief 发送线程

     */

    private class Thread_Send implements Runnable {

        // 发送数据缓存

        private byte[] Buffer_Send = new byte[1024];

        // 发送数据包

        private DatagramPacket Packet_Send;



        /**

         * @param data :需要发送的数据

         * @param len  :数据字节数据

         * @brief 构造函数

         */

        public Thread_Send(byte[] data, int len) {

            // 发送包

            Packet_Send = new DatagramPacket(Buffer_Send, 1024);

            Packet_Send.setData(data);

            Packet_Send.setLength(len);

        }



        @Override

        public void run() {

            try {

                Packet_Send.setPort(LOCAL_PORT_AUDIO);

                Packet_Send.setAddress(InetAddress.getByName(SERVER_IP));

                if (msocketClient != null) {

                    msocketClient.send(Packet_Send);

                    mLastNetworkState = NetworkState.NETWORK_STATE_TXD;

                    mConnectListener.OnConnectStatusCallBack(mLastNetworkState);

                } else {

                    mLastNetworkState = NetworkState.NETWORK_STATE_NULL;

                    mConnectListener.OnConnectStatusCallBack(mLastNetworkState);

                }



            } catch (UnknownHostException e) {

                e.printStackTrace();

                mLastNetworkState = NetworkState.NETWORK_STATE_NULL;

                mConnectListener.OnConnectStatusCallBack(mLastNetworkState);

            } catch (IOException e) {

                e.printStackTrace();

                mLastNetworkState = NetworkState.NETWORK_STATE_NULL;

                mConnectListener.OnConnectStatusCallBack(mLastNetworkState);

            }

        }

    }



    // 获取最后的网络状态

    public NetworkState getLastNetworkState() {

        return mLastNetworkState;

    }



    @SuppressLint("LongLogTag")

    public static String getLocalIpAddress() {

        try {

            for (Enumeration<NetworkInterface> en = NetworkInterface

                    .getNetworkInterfaces(); en.hasMoreElements(); ) {

                NetworkInterface intf = en.nextElement();

                for (Enumeration<InetAddress> enumIpAddr = intf

                        .getInetAddresses(); enumIpAddr.hasMoreElements(); ) {

                    InetAddress inetAddress = enumIpAddr.nextElement();

                    if (!inetAddress.isLoopbackAddress()

             && !inetAddress.isLinkLocalAddress()) {

                        return inetAddress.getHostAddress().toString();

                    }

                }

这里写代码片


        } catch (SocketException ex) {

            Log.e("WifiPreference IpAddress", ex.toString());

        }

        return null;

    }

}

接口SocketConnectListener

public abstract class SocketConnectListener {
    // 网络状态回调
    public abstract void OnConnectStatusCallBack(NetworkState networkState);

    // 接收数据回调
    public abstract void OnReceiverCallBack(int nLength, byte[] data);

}

网络状态枚举类NetworkState

//网络状态枚举类
public enum NetworkState {
    NETWORK_STATE_NULL, // 无状态
    NETWORK_STATE_CONNECT_SUCCEED, // 网络连接成功
    NETWORK_STATE_DISCONNECT_SUCCEED, // 网络断开成功(自身断开)
    NETWORK_STATE_SERVER_DISCONNECT, // 网络被服务器断开
    NETWORK_STATE_CONNECT_FAILLD, // 连接服务器失败,IP/端口不正常
    NETWORK_STATE_CONNECT_ING, // 正在连接过程中...
    NETWORK_STATE_RXD, // 接收数据
    NETWORK_STATE_TXD; // 发送数据
}

主页面连接使用类MainActivity

public class MainActivity extends ActionBarActivity implements View.OnClickListener {
    public static UDPSocketClientManage socketClientManage = null;
//    private String mstrDataString = "";
    private byte[] mstrDataString;
    private TextView textViewRecrive;
    public static byte[] bytes1_up = {(byte) 0xfa,(byte)0x01,(byte)0x05,(byte)0x01};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.button1).setOnClickListener(this);
        findViewById(R.id.button2).setOnClickListener(this);
        findViewById(R.id.button3).setOnClickListener(this);
        TextView loTextView = (TextView) findViewById(R.id.textViewLoca);

        //手机端的连接路由之后IP地址,网络调试助手向目标主机发送的IP地址就是这里获取出来的
        String strLoString = UDPSocketClientManage.getLocalIpAddress();
        if (strLoString != null) {
            loTextView.setText(strLoString);
        }
        textViewRecrive = (TextView) findViewById(R.id.textViewRecrive);
        socketClientManage = new UDPSocketClientManage();
        socketClientManage.RegSocketConnectListener(new SocketConnectListener() {

            @Override
            public void OnReceiverCallBack(int nLength, byte[] data) {
//                mstrDataString = new String(data);
                mstrDataString = data;
                mHandler.sendEmptyMessage(1);
            }

            @Override
            public void OnConnectStatusCallBack(NetworkState networkState) {
                switch (networkState) {
                    case NETWORK_STATE_CONNECT_SUCCEED:
                        mHandler.sendEmptyMessage(0);
                        break;
                    default:
                        break;
                }
            }
        });
    }

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 0: // 接受到消息之后,对UI控件进行修改
                    Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show();
                    break;
                case 1: // 接受到消息之后,对UI控件进行修改
//                    textViewRecrive.append(mstrDataString);
//                    textViewRecrive.setText(bytesToHexString(mstrDataString.getBytes()));
//                    Toast.makeText(MainActivity.this, mstrDataString, Toast.LENGTH_SHORT).show();
                    //下面是以16进制方式来接收
                    String str1 = Integer.toHexString(mstrDataString [0]& 0xFF);
                    String str2 = Integer.toHexString(mstrDataString [1]& 0xFF);
                    String str3 = Integer.toHexString(mstrDataString [2]& 0xFF);
                    String str4 = Integer.toHexString(mstrDataString [3]& 0xFF);
                    if (str1.length() == 1) {
                        str1='0' + str1;
                    }
                    if (str2.length() == 1) {
                        str2='0' + str2;
                    }
                    if (str3.length() == 1) {
                        str3='0' + str3;
                    }
                    if (str4.length() == 1) {
                        str4='0' + str4;
                    }
                    textViewRecrive.setText(str1+" "+str2+" "+str3+" "+str4);
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button1:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        socketClientManage.Connect();
                    }
                }).start();
                break;
            case R.id.button2:
                EditText ipEditText = (EditText) findViewById(R.id.editText1);
                EditText porText = (EditText) findViewById(R.id.editText2);
                String ipString = ipEditText.getText().toString().trim();
                String portString = porText.getText().toString().trim();
                socketClientManage.setNetworkParameter(ipString, portString != null ? Integer.parseInt(portString) : 0);
                Toast.makeText(MainActivity.this, "设置成功", Toast.LENGTH_SHORT).show();
                break;
            case R.id.button3:
               socketClientManage.send(bytes1_up, bytes1_up.length);
                break;
            default:
                break;
        }
    }
}

布局.xml文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="本地IP地址:" />

        <TextView
            android:id="@+id/textViewLoca"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="TextView" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="40dp">

            <requestFocus />
        </EditText>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="PC端的IP地址(也就是发送数据服务器地址):" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="PC端的IP端口(也就是发送数据服务器端口):" />

        <EditText
            android:id="@+id/editText2"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:inputType="number" >

            <requestFocus />
        </EditText>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="发送给PC端的数据" />

        <EditText
            android:id="@+id/editText3"
            android:layout_width="match_parent"
            android:layout_height="40dp" >

            <requestFocus />
        </EditText>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="确定" />

        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="连接" />

        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="发送" />
    </LinearLayout>

    <TextView
        android:id="@+id/textViewRecrive"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="接收到的数据:" />

</LinearLayout>

最后别忘了在AndroidManifest.xml里添加权限

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

以上这些就是全部代码,有不足指出还请大家指出
下面为大家附上源码

猜你喜欢

转载自blog.csdn.net/u013184970/article/details/78599643