고급JAVA 14강 - 네트워크(TCP 소켓)

Whatever·2021년 11월 16일
0

고급 JAVA

목록 보기
14/32

소켓 프로그래밍

2.1 TCP와 UDP
소켓 프로그래밍이란?

  • 소켓을 이용한 통신 프로그래밍을 뜻한다.
  • 소켓(socket)이란, 프로세스간의 통신에 사용되는 양쪽 끝단(end point)
  • 전화할 때 양쪽에 전화기가 필요한 것처럼, 프로세스간의 통신에서도 양쪽에
    소켓이 필요하다.

▶ TCP와 UDP

  • TCP/IP프로토콜에 포함된 프로토콜. OSI 7계층의 전송계층에 해당

TCP

  • 연결기반, 연결 후 통신(전화기), 1:1 통신방식
  • 데이터의 경계 구분 안함
  • 신뢰성있는 데이터 전송
  • 패킷을 관리할 필요 없음
  • 관련 클래스 : Socket, ServerSocket

UDP

  • 비연결기반, 연결없이 통신(소포), 1:1, 1:n, n:n 통신방식
  • 데이터의 경계 구분함
  • 데이터의 전송순서가 바뀔 수 있음
  • 데이터의 수신여부 확인 안함
  • 패킷을 관리해주어야 함
  • 관련 클래스 : DatagramSocket, DatagramPacket, MulticastSocket

2.2 TCP소켓 프로그래밍

  • 클라이언트와 서버간의 1:1 소켓 통신.
  • 서버가 먼저 실행되어 클라이언트의 연결요청을 기다리고 있어야 한다.
    1. 서버는 서버소켓을 사용해서 서버의 특정포트에서 클라이언트의 연결요청을 처리할 준비를 한다.
    2. 클라이언트는 접속할 서버의 IP주소와 포트정보로 소켓을 생성해서 서버에 연결을 요청한다.
    3. 서버소켓은 클라이언트의 연결요청을 받으면 서버에 새로운 소켓을 생성해서 클라이언트의 소켓과
      연결되도록 한다.
    4. 이제 클라이언트의 소켓과 새로 생성된 서버의 소켓은 서버소켓과 관계없이 1:1통신을 한다.

port의 역할
IP로 컴퓨터를 찾아가서 어떤 프로그램을 실행시킬지 선택하는 역할
port 충돌시 나중에 실행되는 프로그램은 실행이 안됨

서버와 클라이언트가 접속이 완료되면 클라이언트가
'd:/d_other/펭귄.jpg'파일을 서버로 전송한다.
서버는 클라이언트가 전송한 파일을 받아서
"d:/d_other/upload/"폴더에 같은 이름으로 저장되도록 한다.

고급JAVA 14강 - 네트워크(TCP소켓)

소켓 프로그래밍

2.1 TCP와 UDP
소켓 프로그래밍이란?

  • 소켓을 이용한 통신 프로그래밍을 뜻한다.
  • 소켓(socket)이란, 프로세스간의 통신에 사용되는 양쪽 끝단(end point)
  • 전화할 때 양쪽에 전화기가 필요한 것처럼, 프로세스간의 통신에서도 양쪽에
    소켓이 필요하다.

▶ TCP와 UDP

  • TCP/IP프로토콜에 포함된 프로토콜. OSI 7계층의 전송계층에 해당

TCP

  • 연결기반, 연결 후 통신(전화기), 1:1 통신방식
  • 데이터의 경계 구분 안함
  • 신뢰성있는 데이터 전송
  • 패킷을 관리할 필요 없음
  • 관련 클래스 : Socket, ServerSocket

UDP

  • 비연결기반, 연결없이 통신(소포), 1:1, 1:n, n:n 통신방식
  • 데이터의 경계 구분함
  • 데이터의 전송순서가 바뀔 수 있음
  • 데이터의 수신여부 확인 안함
  • 패킷을 관리해주어야 함
  • 관련 클래스 : DatagramSocket, DatagramPacket, MulticastSocket

2.2 TCP소켓 프로그래밍

  • 클라이언트와 서버간의 1:1 소켓 통신.
  • 서버가 먼저 실행되어 클라이언트의 연결요청을 기다리고 있어야 한다.
    1. 서버는 서버소켓을 사용해서 서버의 특정포트에서 클라이언트의 연결요청을 처리할 준비를 한다.
    2. 클라이언트는 접속할 서버의 IP주소와 포트정보로 소켓을 생성해서 서버에 연결을 요청한다.
    3. 서버소켓은 클라이언트의 연결요청을 받으면 서버에 새로운 소켓을 생성해서 클라이언트의 소켓과
      연결되도록 한다.
    4. 이제 클라이언트의 소켓과 새로 생성된 서버의 소켓은 서버소켓과 관계없이 1:1통신을 한다.

port의 역할
IP로 컴퓨터를 찾아가서 어떤 프로그램을 실행시킬지 선택하는 역할
port 충돌시 나중에 실행되는 프로그램은 실행이 안됨

서버와 클라이언트가 접속이 완료되면 클라이언트가
'd:/d_other/펭귄.jpg'파일을 서버로 전송한다.
서버는 클라이언트가 전송한 파일을 받아서
"d:/d_other/upload/"폴더에 같은 이름으로 저장되도록 한다.

서버

public class TcpServer01 {

	public static void main(String[] args) throws IOException {
		
		// TCP소켓 통신을 위해서 ServerSocket객체를 생성한다.
		ServerSocket server = new ServerSocket(7777);
		
		System.out.println("서버가 접속을 기다립니다...");
		
		/*
		accept()메서드 
		==> 클라이언트에서의 연결 요청이 올 때까지 기다린다.
		==> 연결 요청이 오면 클라이언트와 연결된 Socket객체를 생성해서 반환한다.
		*/
		
		Socket socket = server.accept();
		
		//accept()메서드 이후의 내용은 연결이 완료되어야만 실행된다.
		System.out.println("클라이언트와 연결이 완료되었습니다.");
		System.out.println();
		
		System.out.println("소켓으로 연결된 상대방에 대한 정보");
		System.out.println("IP주소 : " + socket.getInetAddress().getHostAddress()); 
		//inetaddress객체를 반환 -> 소켓과 연결된 상대방의 아이피 주소
		System.out.println("Port번호 : " + socket.getPort());
		System.out.println();
		
		System.out.println("소켓으로 연결된 로컬 컴퓨터에 대한 정보");
		System.out.println("IP주소 : " + socket.getLocalAddress());
		System.out.println("Port번호 : " + socket.getLocalPort());
		
		// 클라이언트에게 메시지 보내기
		// ==> Socket의 OutputStream객체를 이용하여 전송한다.
		// (socket.getOutputStream()메서드를 이용하여 출력용 스트림 객체를 구할 수 있다.)
		OutputStream out = socket.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		
		// 클라이언트에 메시지를 보낸다. (클라이언트로 출력하는 방식으로 처리한다.)
		dos.writeUTF("환영합니다. 어서오세요.");
		
		System.out.println("클라이언트에게 메시지를 보냈습니다.");
		
		// 스트림과 소켓 닫기
		dos.close();
		socket.close();
		server.close();
		
		
		
		
	}

	
}

서버2

public class TcpClient01 {

	public static void main(String[] args) throws UnknownHostException, IOException {
		/*
			현재 자신 컴퓨터를 나타내는 방법
		  1) 원래의 IP주소 : 예) 192.168.42.125
		  2) 지정된 IP주소 : 127.0.0.1
		  3) 원래의 컴퓨터 이름 : 예) SEM-PC
		  4) 지정된 컴퓨터 이름 : localhost
		*/
		
		String serverIp = "192.168.42.125";
		
		System.out.println(serverIp + "서버에 연결 중입니다...");
		System.out.println();
		
		//서버의 IP주소와 포트번호를 지정하여 Socket객체를 생성한다.
		//socket객체는 생성이 완료되면 해당 서버로 요청신호를 보낸다.
		Socket socket = new Socket(serverIp, 7777);
		
		// 이 부분 이후는 서버와 연결이 완료된 이후에 생성되는 코드이다.
		System.out.println("서버에 연결되었습니다...");
		System.out.println();
		
		// 서버에서 보내온 메시지를 받아서 화면에 출력하기
		// 상대방이 보내온 데이터는 Socket의 InputStream객체를 이용한다.
		// (socket.getInputStream()메서드로 입력용 스트림 객체를 구한다.)
		InputStream is = socket.getInputStream();
		DataInputStream dis = new DataInputStream(is);
		
		// 서버가 보내온 자료를 받아서 출력한다.(자료 입력)
		System.out.println("서버에서 보내온 메시지 : " + dis.readUTF());
		System.out.println();
		
		System.out.println("연결을 종료합니다.");
		
		// 스트림과 소켓 닫기
		dis.close();
		socket.close();
		
	}

}

Sender

// 이 클래스는 Socket을 통해서 메시지를 보내는 역할만 담당하는 클래스이다.
public class Sender extends Thread{
	private Socket socket; //연결용
	private DataOutputStream dos; //보내는 스트림객체 => 전송할 때 필요
	
	private String name; //데이터 구분용
	private Scanner scan; //입력시 필요
	
	// 생성자
	public Sender(Socket socket) {
		this.socket = socket;
		scan = new Scanner(System.in);
		
		System.out.print("이름 입력 : ");
		name = scan.nextLine();
		
		try {
			dos = new DataOutputStream(socket.getOutputStream());
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	@Override
	public void run() {
		while(dos!=null) { //dos => 전송할 객체
			try {
				dos.writeUTF(name + " : " + scan.nextLine());
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	
}

Receiver

// 이 클래스는 Socket을 통해서 메시지를 받아서 화면에 출력하는 역할을 담당하는 클래스이다.

public class Receiver extends Thread {
	private Socket socket;
	private DataInputStream dis;
	
	// 생성자
	public Receiver(Socket socket) {
		this.socket = socket;
		
		try {
			dis = new DataInputStream(socket.getInputStream());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		while(dis!=null) {
			try {
				System.out.println(dis.readUTF());
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
}

TcpServer02

public class TcpServer02 {

	public static void main(String[] args) {
		// ServerSocket객체를 만들고, 클라이언트가 접속해 오면 Socket을 만들어서
		// 메시지를 보내는 클래스와 메시지를 받는 클래스에 이 Socket을 넘겨준다.
		try {
			
			ServerSocket server = new ServerSocket(7777);
			
			System.out.println("서버가 준비중입니다...");
			
			Socket socket = server.accept();
			
			Sender sender = new Sender(socket);
			Receiver receiver = new Receiver(socket);
			
			sender.start();
			receiver.start();
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			
		}

	}

}

TcpClient02

public class TcpClient02 {

	public static void main(String[] args) {
		try {
			Socket socket = new Socket("localhost", 7777);
			System.out.println("서버에 연결되었습니다...");
			
			Sender sender = new Sender(socket);
			Receiver receiver = new Receiver(socket);
			
			sender.start();
			receiver.start();
			
			
		} catch (Exception e) {
			// TODO: handle exception
		}

	}

}

TcpFileServer

public class TcpFileServer {
	// 선생님 답
	private void serverStart() {
		//Socket으로 읽어서 File로 쓴다.
		File saveDir = new File("d:/d_other/upload");
		
		if(!saveDir.exists()) {
			saveDir.mkdirs();
		}
		
		try {
			ServerSocket server = new ServerSocket(7777);
			System.out.println("서버가 준비중입니다.");
			
			Socket socket = server.accept(); // 클라이언트의 요청을 기다린다.
			
			System.out.println("파일 저장 시작...");
			
			//소켓용 입력 스트림 객체 생성
			BufferedInputStream bis = new BufferedInputStream(
				new DataInputStream(socket.getInputStream())
			);
			
			File saveFile = new File(saveDir, "펭귄.jpg");
			
			// 파일 출력용 스트림 객체 생성
			
			BufferedOutputStream bos = new BufferedOutputStream(
				new FileOutputStream(saveFile)
			);
					
			
			byte[] temp = new byte[1024];
			int length = 0;
			
			while((length = bis.read())>0) {
				bos.write(temp,0,length);
			}
			bos.flush();
			
			System.out.println("파일 저장 완료..");
			
			//스트림과 소켓 닫기
			bos.close();
			bis.close();
			socket.close();
			server.close();
			
			
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("파일 저장 실패!!! : " + e.getMessage());
		}
		
	}
	
	public static void main(String[] args) {
		new TcpFileServer().serverStart();
		//-------------------------------------------------선생님 답
		
		//-------------------------------------------------내 답
		//Socket으로 읽어서 File로 쓴다.
	
		//서버 연결을 위한 소켓 생성
		try {
			ServerSocket server = new ServerSocket(7777);
			System.out.println("서버가 접속을 기다립니다.");
			
			//클라이언트의 접속을 기다림
			Socket socket = server.accept(); 
			
			System.out.println("클라이언트와 연결이 완료되었습니다.");
			
			//전송받은 폴더inputstream으로 읽어와서 outputstream으로 "d:/d_other/upload/"에 저장
			InputStream is = socket.getInputStream();
			
			
			String targetFileName = "펭귄.jpg"; 
			//upload폴더가 없으면 만든다.
			File targetFile = new File("D:\\D_Other/upload");
			
			if(targetFile.exists()) {
				targetFile.mkdir();
			}
				
			FileOutputStream fout = 
                       new FileOutputStream(targetFile.getPath() + File.separator + targetFileName);
			BufferedOutputStream bout = new BufferedOutputStream(fout);
			
			int data; 
			while((data=is.read())!=-1) {
				bout.write(data);
			}
			
			is.close();
			bout.close();
			
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}

TcpFileClient

public class TcpFileClient {
	
	//선생님 답
	private void clientStart() {
		File file = new File("d:/d_other/펭귄.jpg");
		String fileName = file.getName();
		if(!file.exists()) {
			System.out.println(fileName + " 파일이 없습니다.");
			System.out.println("작업을 중단 합니다...");
			return;
		}
		
		 try {
			Socket socket = new Socket("localhost", 7777);
			System.out.println("파일 전송 시작...");
			
			//Socket용 OutputStream객체 생성
			DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
			BufferedOutputStream bos = new BufferedOutputStream(dos);
			
			// 파일 입력용 InputStream객체 생성
			BufferedInputStream bis = new BufferedInputStream(
				new FileInputStream(file)
			);
			
			byte[] temp = new byte[1024]; //한번에 1Kbyte씩 읽어옴
			int length = 0;
			
			// 파일 내용을 읽어와 소켓으로 전송하기
			while((length=bis.read(temp))>0) {
				bos.write(temp,0,length);
			}
			
			//buffer사용시 flush사용
			bos.flush();
			
			System.out.println("파일 전송 완료");
			
			bis.close();
			bos.close();
			socket.close();
			
			
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("파일 전송 실패 : " + e.getMessage());
		}
	}
	
	
	public static void main(String[] args) {
		new TcpFileClient().clientStart();
		//---------------------------------------------------선생님 답
		
		//---------------------------------------------------내답
		//파일을 읽어서 Socket으로 쓰기

		// 서버에 접속
		String serverIp = "192.168.42.125";
		
		System.out.println(serverIp + "서버에 연결 중입니다.");
		
		try {
			Socket socket = new Socket(serverIp, 7777);
			System.out.println("서버에 연결되었습니다.");
			
			//파일을 읽어와서 서버에 출력하고 전송
			File file = new File("D:\\D_Other/펭귄.jpg");
		
			//inputStream객체 생성
			FileInputStream fin = new FileInputStream(file);
			BufferedInputStream bin = new BufferedInputStream(fin);
			
			//outputStream객체 생성
			OutputStream out = socket.getOutputStream();
			
			int data; 
			while((data=bin.read())!=-1) {
				out.write(data);
			}
			
			bin.close();
			out.close();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	
		
		
		
	}

}

0개의 댓글