2020.11.18 일지

0후·2020년 11월 18일
0

비트캠프

목록 보기
23/112

오늘의 요약

오늘 배운 것은 1:1 파일주고받는 채팅 만들기이다.

FServer.java

import java.io.*;
import java.net.*;

class FServer {
	String fname = "CHEEZE(치즈) _ Love You(좋아해)(bye).mp4";
	int port = 4000;
	ServerSocket ss;
	Socket s;
	InputStream is; //Node 
	BufferedInputStream bis; //Filter
	FileOutputStream fos; //Node 
	BufferedOutputStream bos; //Filter 
	
	FServer(){
		try{
			ss = new ServerSocket(port);
			pln("파일 서버가 "+port+"번 포트에서 대기중..");
			s = ss.accept();

			is = s.getInputStream(); // 인풋스트림으로 뽑아내야겠지?
			bis = new BufferedInputStream(is, 4096);
			// 일반적으로 바이트 코드를 사용할 땐 인풋스트림을 사용하는게 좋음 
			// 쇼핑카트는 버퍼드인풋스트림으로 생각하면 됨
			
			fos = new FileOutputStream(fname);
			bos = new BufferedOutputStream(fos, 4096);
			// 쇼핑카트 사이즈는 동일하게 해주는 것이 좋다
			receive();
		}catch(IOException ie){
		}
	}
	void receive(){ // 파일 받는 메소드 socket -> file 
		byte bs[] = new byte[1024];
		int i=0;
		long total = 0L;
		try{
			while((i=bis.read(bs)) != -1){ // 파일을 다 읽으면 -1을 리턴하기 때문에 -1이 아닐떄
				bos.write(bs, 0, i); // 0번부터 i번째 까지 써라
				pln("받는 중..."+ ( total+=i ) + "bytes");
			}
			bos.flush(); // i는 byte갯수를 리턴함, 끝까지 가면 -1을 반환한다 그래서 -1이 아니면 까지 조건을 걸어둠
			pln("파일("+fname+": "+total+"bytes) 받기 완료!!");
		}catch(IOException ie){
		}finally{
			closeAll();	
		}
	}
	void closeAll(){
		try{
			bis.close();
			bos.close();
			is.close();
			fos.close();
			s.close();
			ss.close();
		}catch(IOException ie){}
	}
	void pln(String str){
		System.out.println(str);
	}
	public static void main(String[] args) {
		new FServer();
	}
}

FClient.java

import java.io.*;
import java.net.*;

class FClient {  
	Socket s;
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	FileInputStream fis; //Node 
	OutputStream os; //Node 
	BufferedInputStream bis; //Filter
	BufferedOutputStream bos; //Filter 

	String fname = "C://Users//bit//Desktop//CHEEZE(치즈) _ Love You(좋아해)(bye).mp4";

	FClient(){
		connect();
	}
	void connect(){ //서버와 접속
		try{
			p("서버IP(기본:127.0.0.1): ");
			String ip = br.readLine();
			if(ip != null) ip = ip.trim();
			if(ip.length() == 0) ip = "127.0.0.1";
			
			p("PORT(기본:4000): ");
			String portStr = br.readLine();
			if(portStr != null) portStr = portStr.trim();
			if(portStr.length() == 0) portStr = "4000";
			int port = Integer.parseInt(portStr);
			if(port<0 || port>65535){
				pln("범위가 유효하지 않은 포트임");
				connect();
				return;
			}
			s = new Socket(ip, port);
			ready();
		}catch(IOException ie){}
	}
	void ready(){ // 위에서 만든 객체를 채워 넣어야겠지?
		try{
			fis = new FileInputStream(fname);
			bis = new BufferedInputStream(fis, 4096);
			os = s.getOutputStream();
			bos = new BufferedOutputStream(os, 4096);

			send();
		}catch(FileNotFoundException fe){
		}catch(IOException ie){}
	}
	void send(){ //file -> socket
		byte bs[] = new byte[1024]; // 계란판의 사이즈를 키울 경우, bs라는 객체를 만들때 메모리가 커지는 거임, 다만 반복문 돌아가는 횟수가 줄어듬
		int i=0;
		long total = 0L;
		try{
			while((i=bis.read(bs)) != -1){
				bos.write(bs, 0, i);
				pln("전송 중..."+ ( total+=i ) + "bytes"); // 프린팅 하는 건 비효율적이다, 그래서 좀 느려질 수 있음 UI로 바꿔주던가 주석처리 해줘야함
			} 
			bos.flush(); // i는 byte갯수를 리턴함, 끝까지 가면 -1을 반환한다 그래서 -1이 아니면 까지 조건을 걸어둠
			pln("파일("+fname+": "+total+"bytes) 전송 완료!!");
		}catch(IOException ie){
		}finally{
			closeAll();	
		}
	}
	void closeAll(){
		try{
			bis.close();
			bos.close();
			fis.close();
			os.close();
			s.close();
		}catch(IOException ie){}
	}
	void pln(String str){
		System.out.println(str);
	}
	void p(String str){
		System.out.print(str);
	}
	public static void main(String[] args) {
		new FClient();
	}
}

UServer.java

import java.net.*;
import java.io.*;

class UServer {
	DatagramSocket ds; // 메세지함(우체통), 애플리케이션에서 주고 받을 데이터와 관련된 클래스
	DatagramPacket dp; // 메세지틀(편지봉투), 실제 데이터의 전송을 책임지는 클래스
	int port = 5000; // 포트 번호 정수형태로 받음

	UServer(){ // UServer 생성자 호출
		try{ // UServer 생성자의 예외 발생 구문
			ds = new DatagramSocket(port); // DatagramSocket에 port를 담아 호출해준다.

			pln(port + "번에서 UDP서버 대기중.."); // 포트 몇번에서 대기중이라고 모니터에 출력
			byte buf[] = new byte[2048]; // 버퍼를 잡아준다.
			dp = new DatagramPacket(buf, buf.length); // 편지봉투에 버퍼와, 버퍼의 길이를 담아 호출해준다.

			while(true){ // 무한루프 시작, 계속해서 통신할 수 있도록!
				ds.receive(dp); // api 찾아보니 이 소켓에서 데이터 그램 패킷을 받는다, 
				// 이 메서드가 반환되면 DatagramPacket의 버퍼가 수신 된 데이터로 채워진다!
				// 데이터 그램 패킷에는 보낸 사람의 IP 주소와 보낸 사람 컴퓨터의 포트 번호도 포함됨!
				String msg = new String(buf); // 입력 받는 메세지를 새로운 스트링에 buf로 담고
				msg = msg.trim(); // 받은 메세지의 공백을 제거해줌
				pln("Client>>> " + msg); // client>>>의 msg를 모니터에 출력
				for(int i=0; i<buf.length; i++) buf[i]=0; // buf가 한 번 담겨진 배열을 한번 더 쓰기때문에 "가, 나나, 다" 쓰면 "가,나나,다나" 이런식으로 출력됨
				// 이럴때 배열을 새로 만들어주거나 배열을 초기화 해줘야 함 어떻게? 이런 반복문을 통해서 초기화 해줌
			}
		}catch(SocketException se){
		}catch(IOException ie){
		}finally{
			ds.close(); // 마침내 DatagramSocket 을 닫아줌
		}
	}
	void pln(String str){
		System.out.println(str);
	}
	public static void main(String args[]){
		new UServer();
	}
}

UClient.java

import java.net.*;
import java.io.*;

class UClient {
	DatagramSocket ds; // 메세지함(우체통)
	DatagramPacket dp; // 메세지틀(편지봉투)
	int port = 5000; // 포트번호 5000을 적어줌
	String ip; 
	String ipHeader = "192.168.0."; // ip full주소 말고 끝자리만 받으려고 적어주는 변수 
	BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); // 입력 받으려고 node, bridge, filter 모두 한꺼번에 선언해준 것

	void init(){
		inputIp();

		try{
			ds = new DatagramSocket(); // ip가 셋팅이 됐음 데이터 소켓 만들어줌 (UClient 내 try캐치문) 
			while(true){ // 무한루프를 돌리는데, 돌리는 이유는 원래 한 번 전송하고 나면 끝인데 계속 전송하게끔 하려고 무한루프 시작!
				p("전달할 메세지: "); 
				String msg = br.readLine(); // 사용자 입력값 받고
				if(msg != null) msg = msg.trim(); // 공백제거
				byte[] buf = msg.getBytes(); // byte타입의 buf라는 배열에 메세지의 바이트를 얻음
				InetAddress ia = InetAddress.getByName(ip); // InetAddress 클래스는 IP 주소를 표현한 클래스므로, 서버의 ip 주소를 나타냄
				// 자바에서는 모든 IP 주소를 InetAddress 클래스를 사용함
				dp = new DatagramPacket(buf, buf.length, ia, port); 
				// datagrampacket API를 찾으면 여러가지 파라미터를 넣을 수 있는 것들이 있는데, 오버로딩 개념에 의해 이걸 선택함
				// buf, buf의 길이, 아이피 객체를 담은 아이피, 포트번호 이렇게 담는다.
				ds.send(dp); // 그 다음에 ds의 메소드를 send라는 메소드를 사용하여 dp를 보내준다. 
				pln("전송 완료!!");
			}
		}catch(SocketException se){
			init();
		}catch(UnknownHostException ue){
			pln("네트웍상에 해당서버("+ip+")를 찾을 수 없음");
			init(); // 
		}catch(IOException ie){
			init();
		}finally{
			ds.close();
		}
	}
	void inputIp(){ // ip 끝자리만 받는 부분
		try{
			p("IP(끝자리): ");
			String ipTail =  br.readLine();
			if(ipTail != null) ipTail = ipTail.trim(); // tail도 실수로 공백이 들어갈 수 있으므로 공백처리 
			if(ipTail.length() != 0){ // 그냥 엔터를 칠 수도 있으므로, length = 0 이 아닐때만 ip를 생성해라
				ip = ipHeader + ipTail;
			}else{
				inputIp(); // length = 0 이면 한 번 더 입력받게끔 함
			}
		}catch(IOException ie){
			inputIp();
		}
	}
	void pln(String str){
		System.out.println(str);
	}
	void p(String str){
		System.out.print(str);
	}
	public static void main(String[] args) 
	{
		new UClient().init();
	}
}

알게된 개념

TCPUDP
전화쪽지
연결지향비연결지향
일단 네트워크가 연결되면 연결이 종료될때까지 유지데이터의 전송이 끝나면 연결을 끊음
데이터의 소실 확률 없음데이터의 소실 확률 있음
속도가 느림속도가 빠름
profile
휘발방지

0개의 댓글