局域网通信 | 基于广播实现简易聊天室

前言

事情是这个样子的,实验室的那个横向项目有一个需求:同一个 WIFI 下的设备之间可以实现实时的语音聊天。

于是这两天抽空闲时间捣鼓了一下局域网通信。现在基本实现语音通信了,是基于 UDP 广播实现的,但是不知道是 UDP 丢包过于严重还是 PCM 数据采集/播放的问题,导致接收端的声音噪声很大,这个后续再研究研究,看看究竟是个什么问题。

这篇主要记录一下基于 UDP 如何实现(Java语言)一个简易的聊天室,内容包括:UDP 广播、局域网通信、Java 实现广播的发送和接收、测试。

UDP 广播

直观地理解,广播是指同时向子网中的多台设备发送消息,并且所有子网中的设备都可以接收到发送方发来的消息。发送消息的目标地址是全 1 的,也就是说 255.255.255.255。关于 UDP,包括单播、组播、广播等网上有很多介绍文章,这里就不赘述了。

局域网通信

或者准确的说,局域网内通信,因为局域网通信还包括网间通信。网内通信的好处是,不需要介入外网、服务器,通过内网的交换机就可以实现设备之间的通信。这样好处就很明显啦:一个是安全,因为数据不会经过网关流向外网;二一个是效率,因为少了在外网传输的时间,直接通过交换机通信,效率会高很多。这在对实时性要求较高的场合来说尤为重要,例如实时语音。更多关于局域网通信的知识详见网络。

基于 Java 的 UDP 广播发送和接收

我们知道 UDP 是通过数据报传数据的,所以主要涉及到的类就是 DatagramPacket,即数据报包。

看代码:

public class UDPManager {

    private String TAG = UDPManager.class.getName();

    private int sendPort = 10010; // 监听端口
    private int receivePort = 10009; // 发送端口

    public static final int BUFFER_SIZE = 2048;

    public DatagramSocket socket;

    public void init() {

        try {
            //新建一个 DatagramSocket,绑定接收端口
            socket = new DatagramSocket(receivePort);
            //开启数据接收
            openReceiver();
            //发送广播消息
            sendBroadcast("Hello World!");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void openReceiver() {
        //在子线程中接收数据
        new Thread(() -> {
            byte[] buffer = new byte[BUFFER_SIZE];
            DatagramPacket dp = new DatagramPacket(buffer, BUFFER_SIZE);
            while(socket != null) {
                try {
                    socket.receive(dp);
                    String ip = dp.getAddress().getHostAddress();
                    Log.e(TAG, "收到来自 " + ip + " 的消息:" +  new String(buffer).trim());
                    Arrays.fill(buffer, (byte)0); // 清空上一次收到的数据
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * 发送字符串数据
     * */
    public void sendBroadcast(String dataStr) throws IOException {
        if (socket != null) {
            byte[] buffer = dataStr.getBytes();
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("255.255.255.255"), sendPort);
            socket.send(packet);
        }
    }
}

其实非常简单,注释里写得很清楚。指定好发送端口和接收端口就行。

测试

用了下面的工具辅助测试。(有一说一这工具挺好用的)

先创建一个 UDP 测试实例,监听设置中,对 10010 端口进行监听(跟代码中的发送端口一致),连接设置那里,选择的是 UDP 广播,目标 IP 自然也是255.255.255.255,端口与代码中的接收端口一致。

测试结果:

上图中打马赛克那个是我电脑的 IP 地址,上面我的手机和我的电脑进行了如下简单而不失优雅的对话:

手机:hello how are you

电脑:I am fine, thank you, and you?

手机:oh I am fine too

电脑:Oh that is very nice!

测试成功!

本篇完~


 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值