onnnzeoz
article thumbnail

 

기본 웹의 구조는 클라이언트가 먼저 말을 걸 수 밖에 없음

근데 채팅은 양쪽이 얘기해야한다는 특수성이 있음

 

- 채팅 만들기

채팅은 통신이기 때문에 꼭 소켓부터 만들어줘야함, Thread도 상속받아야

ChatClient 얘로 서버에 접속해줌, 여기서 사용한 sender와 receiver는 따로 만들어

public class ChatClient {

	public static void main(String[] args) throws Exception{
		
		//1.소켓 생성
		Socket socket = new Socket("192.168.12.77",5252);
		//2. 예외가없다면 접속성공
		System.out.println("접속성공");
		//3. 요청할거 하고
		Sender sender = new Sender(socket);//sender thread만들고
		Receiver receiver = new Receiver(socket);
		sender.start();
		receiver.start();
		//4. 접속종료
		System.out.println("접속종료");

	}

}

얘는 서버, 설명읽어보면 다 알 수 있음..

 

public class ChatServer {

	public static void main(String[] args) throws Exception{
		
		//1.서버소켓생성
		ServerSocket server = new ServerSocket(5252);
		//2. 클라이언트 확인
		Socket socket = server.accept();
		System.out.println("접속수락");
		//3. 할일한다(상대방에대한 정보니까 stream활용해서 
		Sender sender = new Sender(socket);//sender thread만들
		Receiver receiver = new Receiver(socket);
		sender.start();
		receiver.start();
	}

}

Receiver 클래스, 얘를 통해 받아줌(input), 그리고 한번만 받을거아니고 계속 받아야하니까 while넣어줘 입력하는 코드만 그 사이에 넣어주면돼

//상대한테 받기만하는 스레드->통신할거라서 소켓 무조건 필요
public class Receiver extends Thread{

	private Socket socket; //상대방에대한 정보를 다 가지고 있는거고
	private ObjectInputStream ois; //정보를 보낼 수 있는 통로
	//이기때문에 private으로 막아놓은 것임
	public Receiver(Socket socket) {//다른데서도 쓸거라서 sender는 익명객체로 안만듦
		this.socket = socket;	
	}
	@Override
	public void run() {	
			try {
				ois = new ObjectInputStream(socket.getInputStream());
				
				while (true) {
				String msg = ois.readUTF();
				System.out.println("상대 > "+msg);
				}
				} catch (IOException e) {
				
				e.printStackTrace();
				//예외발생시 ois와socket닫기(생략 닫을 때 trycatch한번 더 들어가니까 복잡해져서 걍 뺌) 
			}	
	}
}

Sender클래스, 얘도 설명 읽으면 다 알 수 있삼..

public class Sender extends Thread{
	private Socket socket = null; // 클래스 전체에서 쓰기위해 따로 빼놓음
	private ObjectOutputStream oos = null; //=null을 쓰나 안쓰나 차이없음, 그냥 아무것도 없다고 보여주는거
	public Sender(Socket socket) {//다른데서도 쓸거라서 sender는 익명객체로 안만듦
		this.socket = socket;
		
	}
	@Override
	public void run() {	
		try {
			//콘솔로 입력을 받고
			Scanner scan = new Scanner(System.in);//자바시스템안에서 쓰는 인풋 
			//소켓으로부터 아웊스트림, 보조스트림
			ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
			
			while(true) {//전송하고 내보내는 것만 while반복하도록
			String msg = scan.nextLine();
			//문자열 받기 위해 nextline,얘도 스캔으로부터 입력받은게 또 있기 전까지는 밑에 문을 실행하지 않음 -> blocking 역할도 함
			System.out.println("당신 > "+msg);
			oos.writeUTF(msg);//전송
			oos.flush();
			
			//내보내기 및 종료
			}
		} catch (IOException e) {//예외처리도 while문 밖에
			
			e.printStackTrace();
			//예외발생시 소켓종료(생략)
		}
	}
}

 

- 채팅에선 문자열만 주고받았다면 이번엔 파일도 주고받기

"C:\\img\\img01.jfif" 이 파일을 "C:/Users/GDJ63/Downloads/"+fileName 여기로 보낼 것임

 

전송할 파일을 읽어오고 그 파일을 Receiver에서 받게끔 다시 보내주기

public class FileSender {

	public static void main(String[] args) throws Exception{
		//client role
		//1.소켓
		Socket socket = new Socket("192.168.12.83",7777);
		System.out.println("접속 성공");
		//2.접속성공(내 저장소에 있는 파일을 읽어올거임)
		//2-1. 주스틂과 보조슮 사용
		File file = new File("C:\\img\\img01.jfif");
		FileInputStream fis = new FileInputStream(file);
		BufferedInputStream bis = new BufferedInputStream(fis);
		
		long size = file.length();
		String fileName = file.getName();
		System.out.println("size : "+size);
		/*
		byte[]arr = new byte[(int) size];
		bis.read(arr);
		*/
		//2-2. 스릍ㄻ으로 데이터 읽어옴
		//2-3. 소켓에서 stream 추출
		
		//3.소켓에서 스트림 추출(OutputStream) 보조스트림
		BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
		DataOutputStream dos = new DataOutputStream(bos);
		//주스트림이 버퍼에탑승한 후 자바 고유 데이터 타입으로 추출하기 위해 data도 탑승함
		
		//4.전송
		dos.writeUTF(fileName);
		dos.writeLong(size);
		//dos.write(arr);
		int data= 0;
		while((data = bis.read()) != -1) {
			dos.write(data);
		}
		
		//5. 내보내기+자원 정리
		dos.flush();
		System.out.println("전송완료");
		dos.close();
		bis.close();
		socket.close();

	}

}

while((data = bis.read()) != -1) {
dos.write(data);
}

이 부분은 

값을 불러온 bis를 read()통해 읽고 그걸 data에 담았는데 (앞에서 변수 선언해줘야함) 그게 만약 -1이 아니라면

data값을 dos에 써라

이 뜻임

-1이 나오면 완료되었다는 뜻이니까

 

이제 Receiver에서 받고 그 사진을 다시 폴더로 전송할거임

그니까 총 순서는 '폴더1 안 파일1  ->Sender -> Receiver - > 폴더2 안에 파일1 입력

public class FileReceiver {

	public static void main(String[] args) throws Exception{
		//server role
		//1. 서버소켓
		ServerSocket server = new ServerSocket(7777);
		
		while(true) {//2. 요청 대기및 수락
			System.out.println("요청대기");
			Socket socket = server.accept();
			System.out.println("요청 수락");
			
			//요청이 들어오는것만다 자기가할건지, 스레드를 하나씩 던져줄건지 정해야함
			//여러 요청을 빠르게 처리하기 위해 스레드를 사용할거임
			Thread th = new Thread() {

				@Override
				public void run() {
					//3. 소켓으로부터 스트림추출(InputStream) + 보조스트림(
					try {
						BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
						DataInputStream dis = new DataInputStream(bis);
						
						//4. 읽어온내용은 자체 저장소에 저장시켜야함 
						String fileName = dis.readUTF();
						long size = dis.readLong();
						System.out.println("size : "+size);
						//byte[]arr = dis.readAllBytes();	
						int data=0;
						
						
						
						//4-1. outputstream -> fileoutputstream.write()
						
						FileOutputStream fos = new FileOutputStream("C:/Users/GDJ63/Downloads/"+fileName);
						BufferedOutputStream bos = new BufferedOutputStream(fos);
						//5. 읽어온 내용 내보내기
						//bos.write(arr);
						while((data = dis.read())!= -1) {
							bos.write(data);
						}
						//6. 자원정리
						bos.flush();
						dis.close();
						bos.close();
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			};
			th.start();
		}
	}
}

요청은 하나만 들어오는게 아니니까 스레드를 만들어서 처리해줬음!


maria db 다운받는 과정

잃어버리면안되는 비번설정


dbeaver 다운받는 과정

 

sql 열때마다 이걸로 열게~ 하는 

 

db기억해야될거 적음 

insert로 집어넣으면 

 

와일드카드=범위신경쓰지 않고 쓰겠다

 

 

profile

onnnzeoz

@onnnzeoz

비전공자의 개발 공부 일지입니다 💦 국비 풀스택 과정 수강중