一起Talk Android吧(第三百三十回:Android中网络通信之UPD通信演示)

Posted talk_8

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起Talk Android吧(第三百三十回:Android中网络通信之UPD通信演示)相关的知识,希望对你有一定的参考价值。

各位看官们,大家好,上一回中咱们说的是android中网络通信之UDP Socket的例子,这一回中咱们说的例子是UDP通信演示。闲话休提,言归正转。让我们一起Talk Android吧!

我们在前面章回中介绍了UDP通信的流程以及UDP Socket接口和数据包,本章回中将介绍如何在通信过程中使用这些接口。

接收端演示

我们定义了一个名叫UDPReceive1的类,类的成员主要是DatagramSocket类和DatagramPacket类的对象,它们代表UDP的Socket和数据包。

接下来我们介绍类中的成员方法:

receiveData()

该方法封装了DatagramSocket类中的receive()方法,它主要用来接收发送方发来的数据,接收的数据存放在数据包中,数据包中存放数据的缓冲区大小为1024字节。接收到数据后,我们把byte类型的数据转换成了string类型,这样方便我们查看。

closeReceiveSocket()

该方法封装了DatagramSocket类中的close()方法,主要用来关闭Socket.

下面是程序的完整代码,请大家参考:

package com.extato;

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

public class UDPReceive1 
    private DatagramSocket mDatagramSocket;
    private DatagramPacket mDatagramPacket;
    private byte [] dataByte;
    int dataLength;

    public UDPReceive1(DatagramSocket socket) 
        mDatagramSocket = socket;
        dataLength = 1024;
        dataByte = new byte[dataLength];
        mDatagramPacket = new DatagramPacket(dataByte,dataLength);
    

    public String receiveData() 
        String receData = null;
        int length;
        byte [] bytes;

        if(mDatagramSocket != null) 
            try 
                mDatagramSocket.receive(mDatagramPacket);
            catch (IOException e) 
                System.out.println("Receive data exception: "+e.toString());
            

            if(mDatagramPacket != null) 

                length = mDatagramPacket.getLength();
                bytes = mDatagramPacket.getData();
                StringBuilder stringBuilder = new StringBuilder();
                for(int i=0; i<length; i++) 
                    stringBuilder.append( String.format("%c",bytes[i]) );
                

//                stringBuilder.append(" IP: ").append(mDatagramPacket.getAddress().getHostAddress());
                stringBuilder.append(" Port: ").append(mDatagramPacket.getPort());
                receData = stringBuilder.toString();
                System.out.println(">>> UDP Receive: "+receData);
            
        

        return  receData;
    

    public void closeReceiveSocket () 
        if(mDatagramSocket != null) // && !mDatagramSocket.isClosed()) 
            System.out.println(">>> Receive Close Socket");
            mDatagramSocket.close();
        
    


发送端演示

我们定义了一个名叫UDPSend1的类,类的成员主要是DatagramSocket类和DatagramPacket类的对象,它们代表UDP的Socket和数据包。类中还有一个int类型的成员变量,它表示UDP通信中的端口号。

接下来我们介绍类中的成员方法:

sendData(String data)

该方法封装了DatagramSocket类中的send()方法,它主要用来发送数据。被发送的数据存放在它的参数中,不过该数据的类型是string,我们不能直接发送,需要把它封装到数据包中后才能发送。

closeSendSocket()

该方法封装了DatagramSocket类中的close()方法,主要用来关闭Socket.

下面是程序的完整代码,请大家参考:

package com.extato;

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

public class UDPSend1 
    private DatagramSocket mUDPSocket;
    private DatagramPacket mDatagramPacket;
    private String mUDPData;
    private int postPort; //this port is used for sending data

    public UDPSend1(DatagramSocket socket, int port) 
        postPort = port;
        mUDPSocket = socket;
    


    public void sendData(String data) 
        if(mUDPSocket != null) 
            try 
                System.out.println("<<< UDP Send: "+data);
                //IP地址使用当前电脑的IP地址
                InetAddress address =  InetAddress.getLocalHost();
                mDatagramPacket = new DatagramPacket(data.getBytes(),data.getBytes().length,address,postPort);
                mUDPSocket.send(mDatagramPacket);
            catch (IOException e) 
                System.out.println("Socket send Data Exception: "+e.toString());
            
        else 
            System.out.println("Socket is null");
        
    


    public void closeSendSocket() 
        if(mUDPSocket != null && mUDPSocket.isClosed()) 
            System.out.println("<<< Send close socket");
            mUDPSocket.close();
        
    



UDP通信演示

我们创建了主程序main,在主程序中分别创建了UDPReceive1类和UDPSend1类的对象,分别表示UDP通信的接收方和发送方。为了分开处理发送方和接收方的程序逻辑,我们创建了两个子线程。

发送方所在的子线程中不停地发送数据,直到最后一条数据为止。接收方所在的子线程不停地接收数据,直到收到最后一条数据为止,然后关闭Socket.

主程序中我们使用ArrayList对象来存放数据,大家在实际项目中可以依据项目需要来自定义数据的存储方式。此外,为了方便演示,主程序中的发送方和接收方共用一个Socket对象,其实使用两个socket对象也是可以的,就是说发送方和接收方各自使用一个Socket对象。不管使用几个Socket对象,只要保证接收方Socket对象中的端口和发送方数据包中的端口一致就可以。大家可以自已动手实践一下。下面是程序的完整代码,请大家参考:

package com.extato;

import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.ArrayList;

public class Main 

    public static void main(String[] args) 
	// write your code hereo
        int port = 3200;
        DatagramSocket datagramSocket = null;
        UDPReceive1 udpReceive1 =  null;
        UDPSend1 udpSend1 = null;

        //Create UDP socket
        try 
            datagramSocket =  new DatagramSocket(port);
        catch (SocketException e) 
           System.out.println("new Socket Exception: "+e.toString()); 
        


        if(datagramSocket != null) 
            udpReceive1 = new UDPReceive1(datagramSocket);
            udpSend1 = new UDPSend1(datagramSocket,port);
        else 
            System.out.println("Socket is null and init send and receive failed.");
        

        UDPReceive1 finalUdpReceive = udpReceive1;
        Thread receiveThread = new Thread(new Runnable() 
            String data = null;
            boolean flag = true;
            @Override
            public void run() 
                while (flag) 
                    data = finalUdpReceive.receiveData();

                    if(data.contains("quit")) 
                        flag = false;
                    
                

                finalUdpReceive.closeReceiveSocket();
            
        );


        ArrayList<String> dataArray = new ArrayList<>();
        for(int i=1; i<6; ++i) 
            dataArray.add("This is data: "+i);
        
        dataArray.add("quit");

        UDPSend1 finalUdpSend = udpSend1;
        Thread sendThread = new Thread(new Runnable() 
            String data = null;

            @Override
            public void run() 
                data = "send data from sendThread";
                for(String item: dataArray) 
                    finalUdpSend.sendData(item);
                
            
        );

        receiveThread.start();
        sendThread.start();
    


下面说一下程序的注意事项:

  1. 我们使用IntelliJ IDEA创建了工程来编译和运行程序,而不是像以往一样使用jdk命令直接编译程序,这样做是为了调试程序方便一些。
  2. 发送和接收数据时都会有IO异常发生,需要处理异常。
  3. 程序中没有指定IP地址,而是默认使用当前电脑的IP地址;
  4. 我们使用最后一条数据为"quit"这个特征巧妙地结束了UDP通信过程,大家在实际项目中可以通过其它方式结束通信,不然会导致线程不停地运行,而且UDP通信也没有结束。

编译并且运行上面的程序,可以得到以下结果:

<<< UDP Send: This is data: 1
<<< UDP Send: This is data: 2
<<< UDP Send: This is data: 3
<<< UDP Send: This is data: 4
<<< UDP Send: This is data: 5
<<< UDP Send: quit
>>> UDP Receive: This is data: 1 Port: 3200
>>> UDP Receive: This is data: 2 Port: 3200
>>> UDP Receive: This is data: 3 Port: 3200
>>> UDP Receive: This is data: 4 Port: 3200
>>> UDP Receive: This is data: 5 Port: 3200
>>> UDP Receive: quit Port: 3200
>>> Receive Close Socket

Process finished with exit code 0

看官们,关于Android中网络通信之UDP通信演示的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!

以上是关于一起Talk Android吧(第三百三十回:Android中网络通信之UPD通信演示)的主要内容,如果未能解决你的问题,请参考以下文章

一起Talk Android吧(第三百三十九回: Android中的OkHttp二)

一起Talk Android吧(第三百三十八回: Android中的OkHttp一)

一起Talk Android吧(第三百三十二回:HTTP协议实践)

一起Talk Android吧(第三百三十一回: HTTP协议概述)

一起Talk Android吧(第三百三十七回: Android中的Volley二)

一起Talk Android吧(第三百三十五回: Android中的HTTP请求二)