[Java] 소켓 프로그래밍2(TCP)

고동이의 IT·2021년 11월 17일
0

Java

목록 보기
32/37
post-thumbnail

서버와 클라이언트가 접속이 완료되면 서버가 'd:/d_other/펭귄.jpg'파일을 클라이언트로 전송하고 'd:/d_other/upload에 저장하는 예제

package kr.or.ddit.basic.tcp;

import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

// 서버와 클라이언트가 접속이 완료되면 서버가 'd:/d_other/펭귄.jpg'파일을
클라이언트로 전송한다.
public class TcpFileServer {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//파일을 읽어서 socket으로 쓰기
		try {
			ServerSocket server = new ServerSocket(7777);
			
			System.out.println("서버가 준비중입니다.");
			Socket socket = server.accept();
			
			System.out.println("클라이언트와 연결이 완료되었습니다.");
			System.out.println();
			
					
			File file = new File("d:/d_Other/툐끼.jpg");
			FileInputStream f = new FileInputStream(file); 
                        //토끼파일을 읽어온다.
			
			OutputStream is = socket.getOutputStream(); 
                       // read, write수행할 수 있게해주는 일꾼으로 생각.
                      상대편으로 보낼것. 툐끼파일을 담을 공간,,,?
			
			int c;
			
			// is에 툐끼파일을 담았슴미다
			while((c=f.read())!=-1){
				is.write(c); //c의 내용을 출력할 수 있도록 is에.
			}
			
			socket.close();
			
			
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

}
package kr.or.ddit.basic.tcp;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;

public class TcpFileClient {

	public static void main(String[] args) throws UnknownHostException, IOException {
		// 소켓으로 읽어서 File로쓴다.
		String serverIp = "192.168.42.138"; 
		System.out.println(serverIp+"서버에 연결중입니다.");
		System.out.println();
		
		// 서버의 IP주소와 포트번호를 지정하여 Socket 객체를 생성한다.
		// Socket객체는 생성이 완료되면 해당 서버로 요청신호를 보낸다.
		Socket socket = new Socket(serverIp, 7777); 
                // throws UnknownHostException, IOException
		
		// 이 부분 이후는 서버와 연결이 완료된 이후에 실행되는 코드이다.
		System.out.println("서버에 연결되었습니다.");
		System.out.println();
		
		try {
			
			
			InputStream is = socket.getInputStream(); 
            //상대방이 보내온 데이터를 Socket의 InputStream객체를 통해 가져와서 
            is에 담는다.
			
			// FileOutputStream: 파일을 작성하기 위해서 사용
			FileOutputStream fo 
                        = new FileOutputStream("d:/d_Other/upload/툐끼.jpg"); 
                        // 받아온 데이터 툐끼를 담을 곳
		
			int c;
			
			while((c=is.read())!=-1){
				fo.write(c);
			}
			
	
			fo.close();
			is.close();
			
			socket.close();
		} catch (IOException e) {
			// TODO: handle exception
		}

	}

}

서버와 클라이언트가 접속이 완료되면 클라이언트가 파일을 선택해서 서버로 전송하고 원하는 이름으로 저장하는 예제

package kr.or.ddit.basic.tcp;

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

public class TcpFileServer011 {
	
	private void serverStart(){
		// 소켓으로 읽어서 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("파일 저장 시작");
			
			// 소켓용 입력 스트림 객체 생성.
			 DataInputStream dis = 	new DataInputStream(socket.getInputStream());
			BufferedInputStream bis = new BufferedInputStream(dis);
			 
			 // 클라이언트가 접속되었을 때 첫번째로 보내온 파일이름을 받는다.
			String fileName = dis.readUTF();
			
			
			File saveFile = new File(saveDir, fileName);
			/*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(temp))>0){
				bos.write(temp, 0, length);
			}
			bos.flush();
			
			System.out.println("파일 저장 완료");
			
			bos.close();
			bis.close();
			socket.close();
			server.close();
			
			
		} catch (Exception e) {
			System.out.println("파일 저장 실패: " + e.getMessage());
		}
	}
	public static void main(String[] args) {
		new TcpFileServer011().serverStart();

	}

}
package kr.or.ddit.basic.tcp;

import java.awt.Panel;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.JFileChooser;

public class TcpFileClient011 {
   enum DialogChoice {open, save}
   
   public File showDialog(DialogChoice choice){
            JFileChooser chooser = new JFileChooser();
            
            chooser.setAcceptAllFileFilterUsed(true);
            
            chooser.setCurrentDirectory(new File("d:/d_other"));
            
            int result = 0;
            if(choice == DialogChoice.open){
               result = chooser.showOpenDialog(new Panel());
            }else if(choice == DialogChoice.save){
               result = chooser.showSaveDialog(new Panel()); 
            }
            
            File selectedFile = null;
            if(result == JFileChooser.APPROVE_OPTION){
               selectedFile = chooser.getSelectedFile();
            }
            return selectedFile;
   }
   
   public void fileCopyStart(){
      System.out.println("복사할 파일을 선택하세요.");
      File open = showDialog(DialogChoice.open);
      if(open == null){
         System.out.println("복사할 파일을 선택하지 않았습니다.");
         System.out.println("복사 작업 중단");
         return;
      }
      if(!open.exists()){
         System.out.println("대상 파일이 존재하지 않습니다.");
         System.out.println("복사 작업 중단");
         return;
      }
      
      System.out.println("저장 경로를 선택하세요.");
      System.out.println("확장자도 같이쓸것");
      File save = showDialog(DialogChoice.save);
      if(save == null){
         System.out.println("복사 경로를 선택하지 않았습니다.");
         System.out.println("복사 작업 중단");
         return;
      }
      
      try {
         FileInputStream fis = new FileInputStream(open);
         FileOutputStream fos = new FileOutputStream(save);
         
         System.out.println("복사 시작");
         System.out.println("복사 중...");
         int c;
         while((c = fis.read()) != -1){
            fos.write(c);
         }
         System.out.println("복사 완료!!");
      } catch (IOException e) {
      }
      System.out.println("프로그램 종료");
   }

   public static void main(String[] args) {
      new TcpFileClient011().fileCopyStart();
   }

}

여러 클라이언트가 동시에 채팅하는 예제

package kr.or.ddit.basic.tcp;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class TcpMultiChatServer {
	// 접속한 클라이언트들을 저장할 Map객체 선언
	// key값: 접속한 사람의 이름, value값 : 접속한 클라이언트의 socket객체
	
	private Map<String, Socket> clientMap;
	
	// 생성자
	public TcpMultiChatServer() {
		// clientMap을 동기화 처리가 되도록 생성한다.
		clientMap = Collections.synchronizedMap(new HashMap<String, Socket>());
		
	}
	
	// clientMap에 저장된 전체 사용자에게 메시지를 전송하는 메서드
	private void sendToAll(String msg){
		// clientMap의 데이터 개수만큼 반복
		for(String name: clientMap.keySet()){
			try {
				// 각 사용자의 Socket을 이용하여 OutputStream객체를 구한다.
				
				DataOutputStream dos = new DataOutputStream(clientMap.get(name).getOutputStream());
				dos.writeUTF(msg);
				
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}
	
	public void serverStart(){
		ServerSocket server = null;
		Socket socket = null;
		try {
			server = new ServerSocket(7777);
			System.out.println("서버가 시작되었습니다.");
			
			while(true){
			socket = server.accept(); // 클라이언트들의 접속을 기다린다.
			System.out.println("["+socket.getInetAddress()+":"+socket.getPort()+ "]에서 접속했습니다.");
			
			// 메시지를 받아서 전체에게 전송하는 Thread객체를 생성하여 작동시킨다.
			ServerReceiver serverThread = new ServerReceiver(socket);
			serverThread.start();
			}
			
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			if(server!=null)try {
				server.close();
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new TcpMultiChatServer().serverStart();
	}
	
	// Inner Class로 서버에서 클라이언트로 메시지를 전송하는 Thread를 만든다.
	class ServerReceiver extends Thread{
		private Socket socket;
		private DataInputStream dis; //사용자가 보낸메시지
		private DataOutputStream dos;
		
		//생성자 
		public ServerReceiver(Socket socket) {
			this.socket = socket;
			
			try {
				// 수신용 객체 생성
				dis = new DataInputStream(socket.getInputStream());
				
				// 송신용 객체 생성
				dos = new DataOutputStream(socket.getOutputStream());
				
			} catch (Exception e) {
				// TODO: handle exception
			}
			
			
		} // 생성자 끝
		
		@Override
		public void run() {
			String name = "";
			try {
				while(true){
					// 클라이언트가 접속이 완료되면 최초로 사용자의 이름을 전송하는데 이 이름이 중복되는지 여부를 feedBack으로 
					// 클라이언트에게 보내준다.
					name = dis.readUTF(); // 클라이언트가 보낸 name을 read로 받음 @@
					
					if(clientMap.containsKey(name)){ //이름이 중복되면 
						dos.writeUTF("이름중복"); //피드백 결과를 write로 클라이언트에게 보내준다.##
					}else{// 이름이 중복되지 않을 때
						dos.writeUTF("ok");
						break;
					}
				}
				// 대화명(이름)을 현재 접속해 있는 다른 클라이언트들에게 대화명(이름)을 이용해서
				// 대화방 참여 메시지를 보낸다.
				sendToAll("["+name+"]님이 대화방에 입장했습니다.");
				
				// 대화명과 클라이언트의 Socket객체를 Map에 저장한다.
				clientMap.put(name, socket);
				
				System.out.println("현재 서버 접속자 수: "
				             + clientMap.size()+"명");
				
				// 한 클라이언트가 보낸 메시지를 전체 클라이언트에게 전송해준다.
				while(dis!=null){
					sendToAll(dis.readUTF());
				}
			} catch (Exception e) {
				// TODO: handle exception
			} finally{ // 한 사용자(클라이언트)가 접속을 끊었을때 finally영역이 실행된다.
				// 사용자 목록에서 해당 클라이언트를 삭제한다.
				clientMap.remove(name);
				
				// 전체 클라이언트에게 누가 대화방을 나갔다는 메시지 전송
				sendToAll("["+ name + "] 님이 대화방을 나갔습니다.");
				System.out.println("["+socket.getInetAddress()+":"+socket.getPort()+ "]에서 접속을 종료했습니다.");
				System.out.println("현재 서버 접속자 수: "
			             + clientMap.size()+"명");
				
				
			}

		}
	}
}
package kr.or.ddit.basic.tcp;

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

public class TcpMultiChatClient {
	
	
	public void clientStart(){
		try {
			
			String serverIp = "localhost";
			
			Socket socket = new Socket(serverIp, 7777);
			System.out.println("서버에 연결되었습니다.");
			System.out.println();
			
			// 메시지를 전송하는 스레드 생성
			ClientSender sender = new ClientSender(socket);
			
			// 메시지를 수신하는 스레드 생성
			ClientReceiver receiver = new ClientReceiver(socket);
			
			sender.start();
			receiver.start();
			
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new TcpMultiChatClient().clientStart();
	}
	
	// 메시지 전송용 스레드
	class ClientSender extends Thread{
		private Socket socket;
		private DataInputStream dis;
		private DataOutputStream dos;
		
		private String name;
		private Scanner scan;
		
		// 생성자
		public ClientSender(Socket socket) { 
			this.socket = socket;
			scan = new Scanner(System.in);
			
			try {
				// 수신용 송신용 객체 생성
				dis = new DataInputStream(socket.getInputStream());
				dos = new DataOutputStream(socket.getOutputStream());
				
				if(dos!=null){
					// 클라이언트가 처음 실행되면 자신의 대화명(이름)을 입력받아 서버로 전송하고 
					// 대화명의 중복 여부를 feedBack으로 받아서 확인한다.
					
					System.out.println("대화명: ");
					String name = scan.nextLine();
					
					while(true){ // 대화명이 중복될때의 경우를위해 반복문으로 묶음
					dos.writeUTF(name); // 이름을 서버로 전송@@
					
					String feedBack = dis.readUTF(); // feedBack결과를 read로 받아서 확인한다.##
					
					if("이름중복".equals(feedBack)){ // 대화명이 중복되면
						System.out.println(name+"은 이름이 중복됩니다.");
						System.out.println("다른 이름을 입력하세요.");
						System.out.println("대화명: ");
					    name = scan.nextLine();
						
					}else{ // 중복되지 않을때
						this.name = name;
						System.out.println(name+"이름으로 대화방에 입장했습니다.");
						break;
						
					}
					
					}
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
	
			@Override
			public void run() {
			try {
				while(dos!=null){
					// 키보드로 입력한 메시지를 서버로 전송한다.
					dos.writeUTF("["+name+"]: "+scan.nextLine());
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
			}
	}
	//메시지 수신용 스레드
	class ClientReceiver extends Thread{
		private Socket socket;
		private DataInputStream dis;
		
		// 생성자
		public ClientReceiver(Socket socket) {
			this.socket = socket;
			try {
				dis = new DataInputStream(socket.getInputStream());
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		
		@Override
		public void run() {
			try {
				while(dis!=null){
					// 서버가 보내온 메시지를 받아서 화면에 출력한다.
					System.out.println(dis.readUTF());
				}
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		
	}
}

profile
삐약..뺙뺙

0개의 댓글