UDP开发入门指南-Java(译)

本文翻译自国外网站的一篇文章,觉得讲的简单易懂,遂翻译出来。一是共享,而是练练手。
原文A Guide To UDP In Java

1.综述

在本指南中,我们探讨的是Java中有关UDP网络通信的知识。
UDP是一种网络通信协议,可以在网络中传输独立的数据包,但是UDP协议不保证传输的有序性和可靠性。UDP是面向无连接,不可靠传输的协议。
尽管大部分的网络通信都是通过TCP(有连接,可靠)来进行的,但接下来我们将要讨论UDP的应用场景。

2.为什么使用UDP

UDP与常见的TCP有很大不同。但是在考虑到UDP的表面缺点之前,更重要的是理解缺乏开销要比TCP快很多。

除了速度,我们还应记住几种通信,如不需要可靠性,但是要求低延迟。视频应用就是一个很好的例子,通过UDP而不是TCP传输。

3.创建UDP应用

创建UDP应用与创建TCP类似,唯一的区别就是我们不需要建立客户端和服务器点对点之间的连接。

设置也很简单。Java自带支持UDP开发的工具包,实在java.net包中。因此,要通过UDP进行网络操作,我们只需要从java.net包中导入所需类:java.net.DatagramSocketjava.net.DatagramPacket.

首先,我们建立一个应答服务器,该服务器可以发消息给他的客户端发送任何返回消息。应答客户端仅可以向服务器发送任意消息。最后,测试应用程序确保一起工作没问题。
首先,我们将构建一个回送服务器,发送回发送给它的任何消息,然后是一个只向服务器发送任意消息的回显客户端,最后,我们将测试应用程序以确保一切正常。

4.服务器

在UDP通信中,单条消息是被装在DatagramPacket中通过DatagramSocket被发送出去的。

我们先建立一个简单的服务端。

/**
* 该服务程序在收到消息后,从DatagramPacket中取出客户端地址和端
*口号,再回一条消息
*/
public class EchoServer extends Thread {
 
    private DatagramSocket socket;
    private boolean running;
    private byte[] buf = new byte[256];
 
    public EchoServer() {
        socket = new DatagramSocket(4445);
    }
 
    public void run() {
        running = true;
 
        while (running) {
            DatagramPacket packet 
              = new DatagramPacket(buf, buf.length);
            socket.receive(packet);
             
            InetAddress address = packet.getAddress();
            int port = packet.getPort();
            packet = new DatagramPacket(buf, buf.length, address, port);
            String received 
              = new String(packet.getData(), 0, packet.getLength());
             
            if (received.equals("end")) {
                running = false;
                continue;
            }
            socket.send(packet);
        }
        socket.close();
    }
}

我们创建了一个发送数据包的全局的DatagramSocket,一个用来装消息的byte数组和一个状态变量。

为了简单,服务器继承自线程Thread,因此可以在run()方法中做需要的工作。

在run方法内部创建了一个while循环,除非running=false或遇到某些错误或者收到来自客户端的终止信息。

在循环顶部,实例化了一个DatagramPacket用来接受消息。

接下来,调用了socket的receive()方法。该方法是阻塞式的,直到收到消息。收到的消息会存放在DatagramPacket中的一个byte数组中。

收到消息后,从收到的DatagramPacket获取客户端的地址和端口号,因为我们需要发送返回消息。

下一步,创建向客户端发送消息的DatagramPacket。注意与收到的DatagramPacket的区别。这个也需要发送的地址和端口号。

5.客户端

现在,我们为该服务器创建一个简单的客户端程序。

public class EchoClient {
    private DatagramSocket socket;
    private InetAddress address;
 
    private byte[] buf;
 
    public EchoClient() {
        socket = new DatagramSocket();
        address = InetAddress.getByName("localhost");
    }
 
    public String sendEcho(String msg) {
        buf = msg.getBytes();
        DatagramPacket packet 
          = new DatagramPacket(buf, buf.length, address, 4445);
        socket.send(packet);
        packet = new DatagramPacket(buf, buf.length);
        socket.receive(packet);
        String received = new String(
          packet.getData(), 0, packet.getLength());
        return received;
    }
 
    public void close() {
        socket.close();
    }
}

客户端代码与服务器的不同。我们有全局的DatagramSocket和服务器的地址。在构造器内部实例化这些变量。

我们有一个独立的方法用来向服务器发送消息和接收服务器返回的消息。

首先需要将String类型的消息转化为byte数组,然后创建一个DatagramPacket用来发送消息。

下一步,发送消息。然后立即将DatagramPacket转化为一个接收的packet。

当服务器返回消息时,将收到的byte数组转化为string并返回。

6.测试

在 UDPTest.java类中,创建了一个简单的测试用来检查我们服务器和客户端的应用程序。

public class UDPTest {
    EchoClient client;
 
    @Before
    public void setup(){
        new EchoServer().start();
        client = new EchoClient();
    }
 
    @Test
    public void whenCanSendAndReceivePacket_thenCorrect() {
        String echo = client.sendEcho("hello server");
        assertEquals("hello server", echo);
        echo = client.sendEcho("server is working");
        assertFalse(echo.equals("hello server"));
    }
 
    @After
    public void tearDown() {
        client.sendEcho("end");
        client.close();
    }
}

setup()方法中,启动服务并创建了一个客户端。在tearDown()方法中,向服务器发送一个终止消息以便能够关闭客户端的同时关闭服务器。

7.总结

在本文中,了解了UDP协议并成功创建了客户端-服务器应用程序,通过UDP实现了通信。

获取示例源码 GitHub project.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容