# 编写数据报客户端和服务器

本节中的示例包含两个应用程序:客户端和服务器。 服务器通过 DatagramSocket 连续接收数据报包。然后返回一段文本信息给客户端, 文本信息从一个文件中读取,如果文件不存在,则只返回当前时间。

客户端发送数据。并接收来自服务端的反馈数据

# 服务端

public class QuoteServer {
    public static void main(String[] args) throws IOException {
        new QuoteServerThread().start();
    }
}

public class QuoteServerThread extends Thread {

    protected DatagramSocket socket = null;
    protected BufferedReader in = null;
    protected boolean moreQuotes = true;

    public QuoteServerThread() throws IOException {
        this("QuoteServerThread");
    }

    public QuoteServerThread(String name) throws IOException {
        super(name);
        // 提供一个监听端口
        socket = new DatagramSocket(4445);

        try {
            // 获得一个文本文件的输入流,如果问津不存在则打印未找到文件信息
            in = new BufferedReader(new FileReader("one-liners.txt"));
        } catch (FileNotFoundException e) {
            System.err.println("Could not open quote file. Serving time instead.");
        }
    }

    public void run() {
        // 按是否还有更多文件内容而决定是否还继续监听请求
        while (moreQuotes) {
            try {
                byte[] buf = new byte[256];

                // 最多接收 256 个字符的数据,等待发送数据报
                // receive request
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                // 阻塞在这里,直到接收到一个数据报
                socket.receive(packet);

                // 反馈给客户端的数据,当文件不存在的时候就返回当前服务器时间
                // figure out response
                String dString = null;
                if (in == null)
                    dString = new Date().toString();
                else
                    dString = getNextQuote();

                buf = dString.getBytes();

                // send the response to the client at "address" and "port"
                // 通过 ip 地址和 端口号,把数据投递出去
                InetAddress address = packet.getAddress();
                int port = packet.getPort();
                packet = new DatagramPacket(buf, buf.length, address, port);
                socket.send(packet);
            } catch (IOException e) {
                e.printStackTrace();
                moreQuotes = false;
            }
        }
        socket.close();
    }

    protected String getNextQuote() {
        String returnValue = null;
        try {
            if ((returnValue = in.readLine()) == null) {
                in.close();
                moreQuotes = false;
                returnValue = "No more quotes. Goodbye.";
            }
        } catch (IOException e) {
            returnValue = "IOException occurred in server.";
        }
        return returnValue;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

# 客户端

public class QuoteClient {
    public static void main(String[] args) throws IOException {
        args = new String[]{"localhost"};

        // 通控制台传递进来要发送数据的服务器
        if (args.length != 1) {
            System.out.println("Usage: java QuoteClient <hostname>");
            return;
        }

        // 构建一个 DatagramSocket
        // get a datagram socket
        DatagramSocket socket = new DatagramSocket();

        // send request
        byte[] buf = new byte[256];
        InetAddress address = InetAddress.getByName(args[0]);
        // 通过 ip 和 端口发送空的数据包
        DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445);
        socket.send(packet);

        // get response
        packet = new DatagramPacket(buf, buf.length);
        // 发完之后就阻塞接收服务器的响应
        socket.receive(packet);

        // 从二进制数据变成字符串打印
        // display response
        String received = new String(packet.getData(), 0, packet.getLength());
        System.out.println("Quote of the Moment: " + received);

        socket.close();
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 测试

服务器打印信息,因为这里我没有文件

Could not open quote file. Serving time instead.

1
2

客户端运行后

Quote of the Moment: Fri Mar 29 16:17:46 CST 2019
1