### 前言

在之前的文章中我们已经讲过了`TCP通讯`的实现,大家如果有兴趣的话,可以参考以下文章:

[Android上实现TCP客户端](http://www.demodashi.com/demo/16980.html)

[Android上实现TCP服务端](http://www.demodashi.com/demo/16981.html)

那么今天就让我们来了解下`android`上 `UDP客户端`的实现吧。

这里我封装了一个`udp客户端`的封装类——`UdpClient`,下面对其使用进行讲解。

今天涉及以下内容:

1. `Tcp`与`Udp`对比

2. `UdpClient`主要方法介绍

3. `UdpClient`在`Activity`中的使用

4. 效果图和项目结构图

先来波效果图

![客户端.gif](/contentImages/image/20200608/w6mm6jwQjN2dV8pW1I4.gif)

![服务端.png](/contentImages/image/20200608/L8qA8Y4kCINJjBuCTcB.png)

#### 一. Tcp与 Udp 对比

`Tcp`与`Udp`作为两种不同的通讯方式。它们之间具备以下不同:

1. `Tcp`通讯需要建立双向连接,而`udp`是不需要建立连接的

2. `Tcp`传输数据以`IO流`的形式,`udp`是以`数据报`的模式。`Tcp`的优势在于传输的数据有序且稳定,不会丢失数据。`udp`传输的数据无序,并且不能保证数据的到达时间及完整性,可能出现`丢包`的情况。

3. 在资源消耗上,`tcp`连接需要经过3次握手,断开也需要消耗资源,而`udp`则在资源消耗上相比较小

有一个很形象的例子来形容他们之间的区别。`tcp`就是打电话,必须打电话的人和接电话的人都在电话机旁,才能建立通话,而`udp`则是`写信`模式,只需要一方信写完寄出去就行了,不需要收信人立刻做出应答,但寄信不保证能准时完整的把消息送达,有可能出现延误或者寄信途中信件丢失,破损的情况,导致信息收不到或收不全。

#### 二. UdpClient主要方法介绍

上面讲过了`tcp`和`udp`的区别,那么下面就来讲讲`udp客户端`封装类`UdpClient`所具备的主要方法吧:

```

/**

* 初始化对象

*

* @param ip 服务端ip

* @param port 约定端口

*/

public UdpClient(String ip,int port)

/**

* 发送消息

*

* @param message 字符串消息

* @param charsetName 字符集,如 TcpConfig.UTF_8 或 TcpConfig.GBK,为null时采用编译器默认字符集

*/

public void sendMessage(String message,String charsetName)

/***

* 接收消息

*

* @param charsetName 字符集,如 TcpConfig.UTF_8 或 TcpConfig.GBK,为null时采用编译器默认字符集

* @return 收到的消息

*/

public String receiveMessage(String charsetName)

/**关闭客户端数据报文**/

public void close()

```

#### 三. UdpClient 在 Activity 中的使用

下面贴出`UdpClient`在`Activity`中使用代码:

```

/**

* Title:测试界面

* description:

* autor:pei

* created on 2020/6/2

*/

public class TempActivity extends AppCompatActivity implements View.OnClickListener{

private TextView mTv;

private Button mBtn1;

private UdpClient mUdpClient;

@Override

protected void onCreate(@Nullable Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_temp);

//初始化控件

initView();

//初始化数据

initData();

//设置监听

setListener();

}

/**初始化控件**/

private void initView(){

mTv=findViewById(R.id.tv);

mBtn1=findViewById(R.id.btn1);

}

/**初始化数据**/

private void initData(){

//192.168.50.152

mUdpClient=new UdpClient("192.168.9.107",12345);

}

/**设置监听**/

private void setListener(){

mBtn1.setOnClickListener(this);

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.btn1://测试

LogUtil.i("=======测试=======");

test();

break;

default:

break;

}

}

/**测试**/

private void test(){

new Thread(new Runnable() {

@Override

public void run() {

String message="我是UDP客户端啊,你是UDP服务端吗?";

mUdpClient.sendMessage(message, "UTF-8");

String result = mUdpClient.receiveMessage("UTF-8");

runOnUiThread(new Runnable() {

@Override

public void run() {

LogUtil.i("=======我来了=====");

mTv.setText(result);

}

});

LogUtil.i("=====客户端收到结果===result=" + result);

}

}).start();

}

@Override

protected void onDestroy() {

super.onDestroy();

//关闭udp链接

if(mUdpClient!=null){

mUdpClient.close();

}

}

}

```

这里需要注意的是,为防止通讯中数据乱码,客户端与服务端发送和接收数据的字符集编码一定要保持一致。

#### 四. 效果图和项目结构图

由于篇幅原因,在下节我将讲述`UDP服务端`的封装使用实现,这里我贴出客户端及服务端运行效果图.

![客户端.gif](/contentImages/image/20200608/w6mm6jwQjN2dV8pW1I4.gif)

![服务端.png](/contentImages/image/20200608/L8qA8Y4kCINJjBuCTcB.png)

![项目结构图.png](/contentImages/image/20200608/8ME6iVjWrdA3PbclH8z.png)

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐