【问题标题】:Why is my TCP system faster than UDP one?为什么我的 TCP 系统比 UDP 系统快?
【发布时间】:2018-12-25 13:12:04
【问题描述】:

我有两个(客户端-服务器-客户端)系统。第一个使用 TCP,第二个使用 UDP。有趣的是,在传输大小为 5-6 mb 的文件时,我的 TCP 使用系统比使用 UDP 的系统更快。问题是因为我的编码错误还是会发生?

TCP 客户端

   try {
       socket = new Socket("localhost", 7755);
   } catch (Exception e) {
       System.out.println(e.getMessage().toString());
   }

   out = new PrintWriter(socket.getOutputStream(), true);

   int i = 0;

   while (file.hasNext()) {
       String line = file.nextLine();
       if (!line.isEmpty()) {
           out.println(line);
       }
       i++;
   }

TCP 服务器

     try {
          serverSocketA = new ServerSocket(7755);
          serverSocketB = new ServerSocket(7760);
     } catch (Exception e) {
          System.out.println("Port error!");
     }
     System.out.println("Server is ready...");
     clientSocketA = serverSocketA.accept();
     clientSocketB = serverSocketB.accept();

     PrintWriter out = new PrintWriter(clientSocketB.getOutputStream(), true);

     BufferedReader in = new BufferedReader(new InputStreamReader(clientSocketA.getInputStream()));

     while((dataFromClientA = in.readLine()) != null) {
          out.println(dataFromClientA);
     }

UDP 服务器

private static byte[] buf = new byte[6];
static Scanner file;

public static void main(String[] args) throws IOException{
    long startTime = System.currentTimeMillis();
    socket = new DatagramSocket();
    address = InetAddress.getByName("localhost");
    file = new Scanner(new File("sentfile.txt"));
    DatagramPacket packet;
    while (file.hasNext()) {
        String line = file.nextLine();
        if (!line.isEmpty()) {
            buf = line.getBytes();
            packet = new DatagramPacket(buf, buf.length, address, 7765);
            socket.send(packet);
        }
    }

UDP 客户端

private static byte[] buffer = new byte[6];
private static byte[] buffer2 = new byte[6];
private static boolean running;
static PrintWriter writer;

public static void main(String[] args) throws IOException {
    udpSocketB = new DatagramSocket();
    address = InetAddress.getByName("localhost");
    udpSocketA = new DatagramSocket(7765);
    running = true;
    DatagramPacket packet;
    while(running) {
        packet = new DatagramPacket(buffer, buffer.length);
        udpSocketA.receive(packet);
        InetAddress address = packet.getAddress();
        int port = packet.getPort();
        packet = new DatagramPacket(buffer, buffer.length, address, port);
        String received = new String(packet.getData(), 0, packet.getLength());
        DatagramPacket packetToB;
        buffer2 = received.getBytes();
        packetToB = new DatagramPacket(buffer2, buffer2.length, address, 7770);
        udpSocketB.send(packetToB);
        if (received.equals("end")) {
            running = false;
            continue;
        }
    }

我只是添加了客户端 1 和服务器代码,其余部分类似。可能是什么原因?

【问题讨论】:

  • 常规:你测量的是什么?确切地?见stackoverflow.com/questions/504103/…
  • 通过服务器将文件从客户端传输到另一个客户端的时间
  • 一个包?认真的吗?
  • 确实很抱歉文件。编辑。 6mb 文件
  • 每行发送一个数据包我们会慢得多,因为如果可以的话,TCP 会批量写入约 1500 字节的 MTU。

标签: java sockets tcp udp


【解决方案1】:

当您通过 TCP 套接字进行写入时,它会尽可能将字节合并成大约 1500 字节的 MTU 数据,从而使数据包标头的开销相对较小。

当您在自己的 UDP 数据包中写入每一行时,每行都会产生开销,可能超过实际发送的数据。

注意:在这两种情况下,您都不需要一次读取一行。您可以一次读取 1 KB 的 byte[] 并打印出来。

public class TCPClient {
    public static void main(String[] args) throws IOException {
        try (Socket socket = new Socket("localhost", 7755);
             FileInputStream fis = new FileInputStream(args[0])) {
            byte[] bytes = new byte[1024];
            OutputStream out = socket.getOutputStream();
            for (int len; (len = fis.read(bytes)) > 0; ) {
                out.write(bytes, 0, len);
            }
        }
    }
}

public class TCPServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(7755);
        System.out.println("Server is ready...");
        try (Socket socket = serverSocket.accept()) {
            byte[] bytes = new byte[1024];
            for (int len; (len = socket.getInputStream().read(bytes)) > 0; )
                System.out.write(bytes, 0, len);
        }
    }
}

您可以使用 UDP 做同样的事情,一次传输 1 KB 并获得相似的吞吐量。

注意:UDP 是有损的,因此您可能会丢失数据包,或者将它们弄乱。

【讨论】:

    【解决方案2】:

    世界上一些最伟大的网络专家已经对 TCP 进行了大量优化。它专为尽可能快速有效地通过 IP 网络发送数据流而设计。它与内核绑定,并且在大多数现代平台上作为一个单元进行了高度优化。你不会超越它,除非它做了一些你不需要的事情,并且你可以从不做那件事中获得显着的好处。

    【讨论】:

    • UPD 是由不太出色的网络专家设计的,并且它与内核的较慢部分相关联?我认为你的回答更像是对类固醇的评论......
    • @GhostCat 我不确定你是认真的还是开玩笑的,但这是一个愚蠢的回应。他正在尝试发送数据流。在一种情况下,他使用操作系统的 TCP 实现来做到这一点。在另一种情况下,他正在使用自己的代码来执行此操作。 TCP 实现具有慢启动、拥塞控制、中断合并、校验和卸载等特性——所有这些都集成到操作系统中,有时甚至集成到内核中。 UDP 不是流协议,因此不能为他做这些事情。
    • 当您将自己的回答与 Peter 的回答进行比较时,也许您会意识到这个问题的真实答案会是什么样子。说真的:当你看到它的核心时,你的答案中没有真正的事实内容。
    • @GhostCat 这个答案实际上并没有回答他的核心问题。是的,他可以做更多 TCP 所做的事情,他可以更接近 TCP 的性能。但是他应该只使用 TCP,因为由于我的回答所解释的原因,他将永远无法匹配它。彼得的回答没有解释为什么 TCP 几乎肯定总是比他的代码快,甚至可能引导他去尝试改进他的代码以匹配 TCP 的愚蠢差事。有一个普遍的神话,即 TCP 比 UDP“更快”,对于像这样的用例,由于我解释的原因,情况正好相反。
    猜你喜欢
    • 2010-11-15
    • 2017-10-27
    • 2012-06-04
    • 1970-01-01
    • 2010-11-22
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    • 2014-10-14
    相关资源
    最近更新 更多