3

I have two (client - server - client) system. First one uses TCP and second one uses UDP. It is interesting that my TCP using system is faster than UDP using one when transferring files in size 5-6 mb. Does problem occurs because of my coding mistakes or can that happen?

TCP Client

   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 Server

     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 Server

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 Client

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;
        }
    }

I just add client1 and server codes and rest is similar. What could be the reason?

Micky A.
  • 31
  • 4

2 Answers2

3

When you write over a TCP socket, it will coalesce bytes if possible into an MTU of data of around ~1500 bytes making the overhead of the packet header relatively small.

When you write each line in its own UDP packet it has an overhead for each line, possibly more than the actual data sent.

Note: in neither case do you need to read a line at a time. You can read say a byte[] of 1 KB at a time and print that.

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);
        }
    }
}

You can do the same thing with UDP, transfering 1 KB at a time and get a similar throughput.

NOTE: UDP is lossy, so you might lose packets, or get them out of order.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

TCP has been heavily optimized by some of the greatest networking experts in the world. It's specifically designed for sending streams of data over IP networks as quickly and efficiently as possible. It's tied into the kernel and they are heavily optimized as a unit on most modern platforms. You're not going to outperform it unless it does something that you don't need and you can obtain a significant benefit from not doing that thing.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • 1
    And UPD has been designed by less great network experts, and it is tied in a slower part of the kernel? I think your answer is more of a comment on steroids ... – GhostCat Jul 17 '18 at 18:53
  • @GhostCat I'm not sure if you're serious or joking, but that's a silly response. He's trying to send a stream of data. In one case he's using the OS's TCP implementation to do it. In the other case, he's using his own code to do it. TCP implementations have features like slow start, congestion control, interrupt coalescing, checksum offload, and so on -- all integrated into the OS and sometimes even the kernel. UDP isn't a stream protocol and so can't do those things for him. – David Schwartz Jul 17 '18 at 18:55
  • And when you compare your response with the one from Peter, maybe you realize how a *real* answer to this question could look like. Seriously: when you look at the core of it, there is no *real* factual content in your answer. – GhostCat Jul 18 '18 at 06:24
  • @GhostCat That answer doesn't actually answer his core question. Yes, he can do more of what TCP does and he can get closer to TCP's performance. But he should just use TCP since he will never be able to match it for the reasons that my answer explained. Peter's answer doesn't explain why TCP will almost certainly always be faster than his code and perhaps even steers him on the fool's errand of trying to improve his code to match TCP. There's a common myth that TCP is "faster" than UDP when, for use cases like this one, the reverse is true for the reason I explained. – David Schwartz Jul 18 '18 at 21:40