[JAVA / NETWORK] UDP 파일 전송

박진용·2022년 9월 5일
0

자바로 UDP로 이것저것 해보고있는데

UDP는 비연결/신뢰성없는 프로토콜이라 일반 텍스트 문서

또는 파일등이 전송자체는 되는데 실행이나 사진, 이미지가 깨진다.

전송 전과 전송 후의 파일 크기는 같으나, 실행 시켜보면 파일이 깨졌다고한다.

UDP는 데이터의 도착순서를 보장하지 않아 파일 크기가 같더라도

내용이 다를수 있고, 또 데이터가 유실될 수 있다고한다.

그래서 문득 UDP로 확실하게 파일을 보낼 방법이 없을까 해서

구글링하면서 구현해봤다

내용

구현자체는 TCP처럼 데이터가 유실되는 경우와 순서를 보장하려고

파일이름이나 데이터를 보내면 잘 받았는지를 확인하는 절차를 추가했다.

목표

사진이나 텍스트파일, 영상을 모두 깨지지 않고 보내는 것

구현

서버

package my.upd.practice;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

public class UDPFileServer {
  
  private String fileName = "";
  
  private int port = 0;
  
  private InetSocketAddress ip = null;
  
  private DatagramSocket socket = null;
  private DatagramPacket packet = null;
  
  private byte[] okSign = "Process Success".getBytes();
  private String finishSign = "Process Finish";
  
  private byte[] buffer = null;
  private int size = 2048;
  
  public UDPFileServer() {
    
    try {
      
      port = 32123;
      ip = new InetSocketAddress(InetAddress.getByName("localhost"), port);
      socket = new DatagramSocket(ip);
    } catch (Exception e) {
      e.printStackTrace();
    }
    
  }
  
  /*
  * 파일 전송 시작전
  * 클라이언트가 보내주는 파일 이름 체크
  * */
  public void fileNameCheck() {
    buffer = new byte[size];
    packet = new DatagramPacket(buffer, size);
    
    try {
      socket.receive(packet);

      fileName = new String(packet.getData(), 0, packet.getLength());
      System.out.println("Client send(File name) : " + fileName);
      
      packet = new DatagramPacket(fileName.getBytes(), fileName.getBytes().length, packet.getAddress(), packet.getPort());
      socket.send(packet);
      
      packet = new DatagramPacket(buffer, size);
      socket.receive(packet);
      
      System.out.print("NAME CHECK: ");
      
      if (new String(packet.getData(), 0, packet.getLength()).equals("ok")) {
        System.out.println("name check success, transfer start");
      } else {
        System.out.println("name check failed, process end");
        System.exit(1);
      }
      
      
      
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  
  public void startProcess() {

    File file = new File(fileName);
    
    int readSize = 0;
    int count = 0;
    
    try {
      packet = new DatagramPacket(buffer, 0, size, ip);
      socket.receive(packet);
      System.out.println(new String(packet.getData(), 0, packet.getLength()));
      
      BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
      
      
      while ((readSize = packet.getLength()) != 0) {
        String msg = new String(buffer, 0, readSize);
        System.out.println(msg);
        
        if (msg.equals(finishSign)) {
          System.out.println("finished");
          break;
        }
        
        bos.write(buffer, 0, readSize);
        bos.flush();
        
        packet.setData(okSign, 0, okSign.length);
        socket.send(packet);
        
        packet.setData(buffer, 0, size);
        socket.receive(packet);
      }
      
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  public void start() {
    fileNameCheck();
    startProcess();
    
  }
  
  
  
  
  public static void main(String[] args) {
    
    System.out.println("<<UDP FILE SERVER STARTING...>>>");
    
    UDPFileServer server = new UDPFileServer();
    server.start();
  }
  
}

클라이언트

package my.upd.practice;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.*;

public class UDPFileTransfer {

private String fileName = "sample.mp4";
private int serverPort = 32123;
private InetAddress serverIp = null;

private DatagramSocket socket = null;
private DatagramPacket packet = null;

private String okSign = "Process Success";
private byte[] finishSign = "Process Finish".getBytes();

private byte[] buffer = null;
private int bufferSize = 2048;

UDPFileTransfer() {
try {
serverIp = InetAddress.getByName("localhost");
socket = new DatagramSocket();
} catch (UnknownHostException | SocketException e) {
e.printStackTrace();
}
}

public boolean initConnection() {
System.out.println("File name to transfer: " + fileName);
buffer = new byte[bufferSize];

try {
  packet = new DatagramPacket(fileName.getBytes(), fileName.getBytes().length, serverIp, serverPort);
  socket.send(packet);
  
  packet = new DatagramPacket(buffer, buffer.length, serverIp, serverPort);
  socket.receive(packet);
  
  String checkFileName = new String(packet.getData(), 0, packet.getLength());
  
  if (checkFileName.equals(fileName)) {
    packet = new DatagramPacket("ok".getBytes(), "ok".getBytes().length, serverIp, serverPort);
    socket.send(packet);
  } else {
    packet = new DatagramPacket("fail".getBytes(), "fail".getBytes().length, serverIp, serverPort);
    socket.send(packet);
  }
  
} catch (Exception e) {
  e.printStackTrace();
}

return true;

}

public boolean checkData(String msg) {

if (msg.equals(okSign)) {
  return true;
}

return false;

}

public void sendFile() {
int read = 0;
int count = 0;
byte[] tmpBuf = new byte[bufferSize];

try {
  RandomAccessFile file = new RandomAccessFile("src/" + fileName, "r");
  
  packet = new DatagramPacket(buffer, bufferSize, serverIp, serverPort);
  while(( read = file.read(buffer, 0, bufferSize)) != -1) {
    System.out.println("ReadSize : "+ read);
    packet.setData(buffer, 0, read);
    socket.send(packet);
    count++;
    
    while (true) {
      packet.setData(tmpBuf, 0, bufferSize);
      socket.receive(packet);
      
      String msg = new String(packet.getData(), 0, packet.getLength());
      if (checkData(msg)) {
        break;
      } else {
        packet.setData(buffer, 0, bufferSize);
        socket.send(packet);
      }
    }
  }
  
  packet.setData("Process Finish".getBytes(), 0, "Process Finish".getBytes().length);
  socket.send(packet);
  
  
} catch (Exception e) {
  e.printStackTrace();
}

}

public static void main(String[] args) {
UDPFileTransfer client = new UDPFileTransfer();
System.out.println("String UDP file transper...");

client.initConnection();
client.sendFile();

}

}

결과

mp4파일을 전송해서 로그가 조금 지저문하지만

전송된 mp4파일도 문제 없이 실행된다!

후기

그냥 파일전송은 TCP로 진행하는것이 좀 더 나을 것같다

다만 UDP는 속도 면에서 이점이 있다고하니까 알아두면

언제가 쓸 일이 있을지도 모르겠다.

profile
하루하루 깊어지자

0개의 댓글