네트워크를 통해 파일을 전송하는것은 Stream에서 파일 전송의 활용이라고 보면 된다.


Stream을 통해서 읽어온 데이터를 그대로 전송하면 된다.


네트워크 부분은 대부분 비슷하기 때문에 설명은 많이 적지 않고 코드의 주석을 통해 설명




Receiver 클래스



package chap12.exam07.file;

import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
// 직접 만들어본 리시버
public class Receiver {

	public static void main(String[] args) throws Exception {
		// 데이터를 받으려면 항시 대기하여야 하는데 while문으로 묶어버리면
		// 아래의 코드가 작동되지 않으므로 따로 스레드를 만들어야함
		String path = "C:/img/temp2/aaa.pdf";
		// 1. DatagramSocket 생성
		DatagramSocket socket = new DatagramSocket(5001);
		FileOutputStream fos = new FileOutputStream(path);
		
		Thread th = new Thread(){
			@Override
			public void run() {
				// 2. DatagramPacket 준비 (한번에 받은 메시지 크기)
				DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
				while(true) {
					try {
						socket.receive(packet);		// 3. 데이터 수신
						byte[] character = packet.getData();
						fos.write(character);
					} catch (IOException e) {
						e.printStackTrace();
						break;
					}
				}
			}
		};
		th.setDaemon(true); // main이 끝나면 같이 죽도록 설정
		th.start(); // 스레드 실행
		// 5. 자원 정리
		Thread.sleep(10000);
		socket.close(); // 소켓을 닫고
		// 종료		
	}

}


Main FileReceiver



package chap12.exam07.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class FileReceiver {

	public static void main(String[] args) throws Exception {
		// 1. 서버소켓 생성
		ServerSocket server = new ServerSocket(7777);

		while(true) { // 대기
			System.out.println("요청 대기중...");
			// 2. 연결 수락
			Socket socket = server.accept();
			System.out.println("수락");

			Thread th = new Thread() {

				@Override
				public void run() {
					try {
						// 3. 파일 위치 지정
						String path = "C:/img/temp2/";
						
						// 4. 스트림 준비
						BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); // 파일명 받기
						DataInputStream dis = new DataInputStream(bis);
						path += dis.readUTF();
						System.out.println(path);
						FileOutputStream fos = new FileOutputStream(path);  // 파일 받아오기
						BufferedOutputStream bos = new BufferedOutputStream(fos);

						// 5. 읽기 -> 쓰기
						// 배열로 받을 경우 다른 IP로 전송 시 파일이 깨질 수 있음
						byte[] source = new byte[1024];
						while(dis.read(source) != -1) {
							bos.write(source);
						}
						
//						int data;
//						while((data = dis.read() != -1)) {
//							bos.write(data);
//						}
						bos.flush();
						System.out.println("다운로드 완료");
						bos.close();
						fos.close();
						bis.close();
						dis.close();
						socket.close();
					}catch (Exception e) {
						System.out.println(e.toString());
					}
				}
			};
			th.start();
		}
	}

}


Sender 클래스



package chap12.exam07.file;

import java.io.FileInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class Sender { // 직접 만들어본 sender

	public static void main(String[] args) throws Exception {
		String pathInput = "C:/img/10multi.pdf";
		FileInputStream fis = new FileInputStream(pathInput);
		// 1. DatagramSocket 생성
		DatagramSocket socket = new DatagramSocket();
		int i = 0;
		byte[] buffer = new byte[1024];
		
		while(fis.read(buffer)!=-1) { // -1 == EOF
			// 4. 내보내기
			DatagramPacket packet = new DatagramPacket(buffer, buffer.length, new InetSocketAddress("localhost", 5001));
			socket.send(packet);
			i++;
			System.out.println("파일 복사중... " + i);
		}


		fis.close();
		socket.close();

	}

}


Main FileSender



package chap12.exam07.file;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.net.Socket;

public class FileSender {

	public static void main(String[] args) throws Exception {
		// 1. 파일 위치
		String path = "C:/img/10multi.pdf";
		int i = 0;
		// 2. 스트림 준비 + 소켓(스트림)
		try(
		FileInputStream fis = new FileInputStream(path);
		BufferedInputStream bis = new BufferedInputStream(fis);
		Socket socket = new Socket("여기에 IP를 입력해야 정상적으로 동작해요">", 7777);
		BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
		DataOutputStream dos = new DataOutputStream(bos);
		){
			// 3. 읽어오기 -> 전송(파일 바이너리 + 파일 명)
			String[] name = path.split("/");
			dos.writeUTF(name[name.length-1]); // -1번방의 내용을 전송
			dos.flush();
			
			// 파일 바이너리 전송
			byte[] source = new byte[1024];
			while(bis.read(source) != -1 ) {  // 한번의 루프로 1024바이트(1kb) 전송
				dos.write(source);
				// 전송 진행율 표시를 어떻게 할 것인가????
				i++;
				System.out.println("파일 전송중..." + i + " / " + source.length);
			}
			dos.flush();
			System.out.println("전송 완료...!");
			
		} catch (Exception e) {
			System.out.println(e.toString());
		}
	}

}


File Sender의 19번째 줄에 접속할 대상의 IP를 입력해주어야 한다.


그리고 서버는 이클립스에서 실행하고


클라이언트를 따로 실행해야 하는데


https://qdgbjsdnb.tistory.com/79 를 참조하여 cmd에서 클라이언트를 작동해보자.





'개념 및 코딩 > 10.네트워크' 카테고리의 다른 글

[JAVA]10-06.UDP, Datagram  (0) 2018.09.27
[JAVA]10-05.N:M MultiChat Server, Client  (2) 2018.09.27
[JAVA]10-04.1:1 Chat Server, Client  (0) 2018.09.27
[JAVA]10-03.Echo Server, Client  (0) 2018.09.27
[JAVA]10-02.TCP Server, Client  (0) 2018.09.27

UDP는 TCP와 달리 DatagramSocket과 DatagramPacket을 사용한다.


TCP와의 차이점으로는 일방적인 전송을 하고 확인 작업이 없기 때문에 속도가 빠르지만


정확도가 낮다




Server가 될 Receiver


package chap12.exam06.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

public class Receiver {

	public static void main(String[] args) throws Exception {
		// 데이터를 받으려면 항시 대기하여야 하는데 while문으로 묶어버리면
		// 아래의 코드가 작동되지 않으므로 따로 스레드를 만들어야함

		// 1. DatagramSocket 생성
		DatagramSocket socket = new DatagramSocket(5001);

		Thread th = new Thread(){

			@Override
			public void run() {
				// 2. DatagramPacket 준비 (한번에 받은 메시지 크기)
				DatagramPacket packet = new DatagramPacket(new byte[100],  100);
				while(true) {
					try {
						socket.receive(packet);		// 3. 데이터 수신
						byte[] character = packet.getData();
						String data = new String(character,  "UTF-8").replace('\0', ' ');
						System.out.println(data);		// 4. 받은 데이터 출력
					} catch (IOException e) {
						e.printStackTrace();
						break;
					}
				}
			}
		};
		th.setDaemon(true); // main이 끝나면 같이 죽도록 설정
		th.start(); // 스레드 실행
		// 5. 자원 정리
		Thread.sleep(10000);
		socket.close(); // 소켓을 닫고
		// 종료		
	}

}


Client가 될 Sender


package chap12.exam06.udp;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;

public class Sender {

	public static void main(String[] args) throws Exception {
		// 1. DatagramSocket 생성
		DatagramSocket socket = new DatagramSocket();
		// 2. 보낼 메시지 준비
		for(int i = 1; i <= 3; i++) {
			String msg = "data_" + i;
			byte[] arr = msg.getBytes();
			// 3. DatagramPacket으로 전송
			DatagramPacket packet = new DatagramPacket(arr,  arr.length, new InetSocketAddress("localhost", 5001));
			socket.send(packet);
		}

		// 4. 자원 반납
		socket.close();
		
	}

}



서버는 이클립스에서 실행하고


클라이언트를 따로 실행해야 하는데


https://qdgbjsdnb.tistory.com/79 를 참조하여 cmd에서 클라이언트를 작동해보자.



1:1 채팅을 조금 바꾼 다대다, N:M 멀티 채팅이다.


전과 다른점으로는 클라이언트와 서버에 사용할 Receiver, Sender 따로 있는 점이다.





서버 기능을 가지고 있는 ServerManager 클래스


package chap12.exam05.multichat;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class ServerManager extends Thread {
	Socket socket;
	DataInputStream in;
	DataOutputStream out;
	// 서버이기에 in 먼저 일어남
	
	public ServerManager(Socket socket) throws IOException {
		this.socket = socket;
		in= new DataInputStream(socket.getInputStream());
		sendMsg(socket.getPort() + "님이 입장 하였습니다.");
	}

	@Override
	public void run() { // 서버는 메시지를 감지해야 하므로 in을 이용
		while(in != null) {
			try {
				sendMsg(socket.getPort()+"> " + in.readUTF());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			in.close();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public void sendMsg(String msg) throws IOException { // MultiServer의 List에서 소켓 리스트를 받아옴
		System.out.println(msg);
		for(Socket soc : MultiServer.list) {
			out = new DataOutputStream(soc.getOutputStream());
			out.writeUTF(msg);
			out.flush();
		}
	}


}




ServerManager를 불러오는 MultiServer


package chap12.exam05.multichat;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class MultiServer {
	static ArrayList<Socket> list = new ArrayList<>();
	
	public static void main(String[] args) throws IOException {
		
		ServerManager manager;
		Socket socket;
		ServerSocket server = new ServerSocket(5252);
		System.out.println("서버 실행 중");
		
		while(true) {
			socket = server.accept(); // 소켓을 기다림
			list.add(socket); // 추가
			manager = new ServerManager(socket);
			manager.start();
		}
	}

}



다음으로는 Client에 필요한 클래스와 메인 클라이언트


Sender


package chap12.exam05.multichat;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;

public class ClientSender extends Thread {
	Socket socket;
	DataOutputStream out;
	
	public ClientSender(Socket socket) throws IOException {
		// 초기화와 동시에 스트림도 잡아주면 효율적
		this.socket = socket;
		out = new DataOutputStream(socket.getOutputStream());
		// socket.getOutputStream을 그대로 형변환 해도 된다.
	}

	@Override
	public void run() {
		while(out != null) {
			System.out.print("당신>");
			Scanner scan = new Scanner(System.in);
			
			try {
				out.writeUTF(scan.nextLine());
				out.flush();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}



Receiver



package chap12.exam05.multichat;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

public class ClientReceiver extends Thread {
	Socket socket;
	DataInputStream in;
	
	public ClientReceiver(Socket socket) throws IOException {
		this.socket = socket;
		in = new DataInputStream(socket.getInputStream());
		// Sender와 크게 차이 없음
	}

	@Override
	public void run() {
		while(in != null) {
			try {
				System.out.println(in.readUTF());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}



실질적으로 동작할 Main MultiClient



package chap12.exam05.multichat;

import java.net.Socket;

public class MultiClient {

	public static void main(String[] args) throws Exception {
		Socket socket = new Socket("여기에 IP를 입력해야 정상적으로 동작해요", 5252);
		System.out.println("연결 성공");
		ClientReceiver receiver = new ClientReceiver(socket);
		ClientSender sender = new ClientSender(socket);
		
		receiver.start();
		sender.start();
	}

}




8번째 줄에 접속할 대상의 IP를 입력해주어야 하고 1개의 컴퓨터로 테스트 할 경우


대상 Server가 자기 자신이므로 자신의 IP를 입력하면 된다.


그리고 서버는 이클립스에서 실행하고


클라이언트를 따로 실행해야 하는데


https://qdgbjsdnb.tistory.com/79 를 참조하여 cmd에서 클라이언트를 작동해보자.



'개념 및 코딩 > 10.네트워크' 카테고리의 다른 글

[JAVA]10-06.File Sender, Receiver  (0) 2018.09.27
[JAVA]10-06.UDP, Datagram  (0) 2018.09.27
[JAVA]10-04.1:1 Chat Server, Client  (0) 2018.09.27
[JAVA]10-03.Echo Server, Client  (0) 2018.09.27
[JAVA]10-02.TCP Server, Client  (0) 2018.09.27

+ Recent posts