ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바 네트워크 네트워크 입출력 (1) - TCP
    언어/JAVA 2023. 8. 22. 19:19

     

    1. 네트워크 기초 

     

    - 네트워크는 여러 컴퓨터들을 통신 회선으로 연결하는 것 

    - LAN은 가정,회사,건물,특정 영역에 존재하는 컴퓨터 연결

    - WAN은 LAN을 연결한 것이다. (WAN이 흔히 말하는 인터넷이다)

     

    출처: 이것이 자바다

    - LAN과 LAN을 라우터가 연결

    - 라우터와 LAN은 스위치로 연결 

     

    1.2 서버와 클라이언트 

     

    - 네트워크에서 유무선으로 컴퓨터가 연결되어 있다면, 실제로 데이터 주고받는 행위는 프로그램들이 한다.

    - 서비스를 제공하는 프로그램서버, 서비스 요청하는 프로그램클라이언트라 부른다.

    - 인터넷을 통해서 두 프로그램이 통신하기 위해서는 클라이언트가 서비스 요청, 서버는 처리 결과 응답으로 제공한다.

     

    1.3 ip주소 

     

    - 컴퓨터의 고유주소이다. 컴퓨터마다 받는 것이 아니라, 네트워크 어답터(LAN 카드)마다 할당

    - 두개의 어댑터가 연결되어 있다면, 두 개의 IP주소를 할당받을 수 있다.

    - 연결할 상대의 IP주소도 알아야 통신할 수 있다.

    - 프로그램은 DNS서버를 이용해서 컴퓨터 IP 주소를 검색한다.

    - DNS는 도메인 이름으로 IP를 등록하는 저장소이다. 

    - 웹 브라우저는 웹 서버와 통신하는 대표적인 클라이언트 프로그램으로, 사용자가 입력한 도메인 이름으로 DNS서버로 ip주소를 검색해서 웹서버와 연결해서 웹 페이지를 받는다.

     

    * 윈도우 ip설정에 보면, DNS와 ip주소는 자동으로 부여된다. (Switch가 알아서 자동 생성) 

      동일한 컴퓨터는 대부분 같은 ip를 부여받는데, 이는 switch가 pc의 물리적 주소로(Map address) 구분할 수 있기 때문이다. (어뎁터, LAN카드별 고유 식별번호)

    *네트워크 통신을 위해서는 외부 IP도 필요하다 (LAN과 LAN, 라우터 IP 등 인터넷상에서 사용하는 IP필요)

    * ip주소나 DNS서버는 네트워크 관리자로부터 받아온다. -> 집에 있는 네트워크 장비는 대부분 스위치로 이를 통해서 자동으로 부여받은 것 

     

    1.4 Port번호

     

    - 한대의 컴퓨터에 다양한 서버 프로그램이 실행될 수 있다. 

    - 클라이언트는 서버 ip뿐 아니라, 서버 프로그램에 할당된 port번호도 알아야 연결될 수 있다.

    - port는 운영체제가 관리하는 서버 프로그램의 연결 번호이다. 서버는 특정 포트번호에 바인딩한다.

     

    출처: https://ittrue.tistory.com/185

    - 클라이언트도 서버에서 보낸 정보를 얻기 위해선 port가 필요한데, 서버 처럼 고정적인 port번호에 바인딩 되는 것이 아니라, 운영체제에 의해 자동으로 부여되는 번호 사용한다.

    - 클라이언트 포트번호는 서버로 요청을 보낼 때 함께 전송되어 서버가 클라이언트로 데이터 보낼 때 사용된다.

     

    2. IP주소 얻기 

     

    - 자바는 IP주소를 InetAddress로 표현한다. 

    - 이를 통해 local, 외부, DNS를 통한 ip를 얻을 수 있다.

    public class IPget{
    
    public static void main(String[] args){
    
    	try{
        	//로컬 ip얻기
        	InetAddress local = InetAddress.getLocalHost();
            
            InetAddress[] iaArr = InetAddress.getAllByName("www.naver.com");
            for(InetAddress remote : iaArr){
            	//..
            }
       
        }catch(Exception e){
        
        }
    
    }
    
    
    }

     

    3. TCP 네트워킹 

     

    - IP주소로 프로그램들이 통신할 때는 약속한 데이터 전송 규약이 있다. 이를 전송용 프로토콜이라고 부른다.

    - 인터넷 전송용 프로토콜은 TCP,UDP가 있다.

    - TCP는 연결형 프로토콜, 상대방이 연결된 상태에서 데이터 주고 받음

    - 서버가 연결을 수락하면 통신 회선이 고정되고, 데이터는 고정 회선을 통해 전달됨 

    - TCP는 보낸 데이터가 순서대로 전달되며 손실이 발생하지 않는다.

    - TCP는 웹 브라우저(클라이언트 프로그램)가 웹 서버에 연결할 때 사용된다.

    - TCP 네트워킹을 위해 ServerSocket과 Soket 클래스를 제공한다.

     

    출처: 이것이 자바다

     - ip/port는 컴퓨터와 프로그램 구분하기 위한 번호 

     - 실제 연결, 데이터 전송은 Soket을 사용 

     - 클라이언트에서 서버로 요청을 보내면 서버소켓이 이를 받고, 소켓을 생성 서버에서 생성된 소켓을 통해 통신한다.

     

    3.1 TCP서버 

     

    - 서버소켓 생성

    ServerSocket serverSocket = new ServerSocket(50001);
    
    //서버소켓 생성 후에 바인드
    ServerSocket serverSocket = new ServerSocket();
    serverSocket.bind(new InetSocketAddress(50001));
    
    // 여러 개의 ip가 컴퓨터에 할당되어 있는 경우, 특정 ip에서만 서비스하고 싶을 때 
    ServerSocket serverSocket = new ServerSocket();
    serverSocket.bind(new InetSocketAddress("ip주소",50001));

    - 만약 Port 이미 다른 프로그램에서 사용 중이라면 BindException이 발생

    Socket socket = serverSocket.accept();
    InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
    String clientIp = isa.getHostName();
    String protNo = isa.getPort();
    
    //소켓 종료 
    serverSocket.close();

    - 서버 프로그램

    public class TCPServerExam {
        private static ServerSocket serverSocket;
        public static void main(String[] args) {
            System.out.println("---------------------------------");
            System.out.println("서버를 종료하려면, q 혹은 Q 입력하고 Enter를 입력하셔요");
    
    
            //TCPServer시작
            startServer();
    
            Scanner sc = new Scanner(System.in);
            while(true){
                String input = sc.nextLine();
                if(input.toLowerCase().equals("q")) {
                    break;
                }
            }
            sc.close();
    
            //서버종료
            stopServer();
        }
    
        public static void startServer(){
            //작업스레드 정의
            Thread thread = new Thread(){
                @Override
                public void run(){
                    //서버소켓+바인딩
    
                    try {
                        serverSocket = new ServerSocket(50001);
                        System.out.println("서버시작");
    
                        while(true){ //여러 클라이언트 연결요청받기 위해 계속 기다림
                                     //하나의 소켓은 하나의 연결요청 기다림
                            System.out.println("[서버] 연결요청을 기다림\n");
                            Socket soket = serverSocket.accept();
    
                            InetSocketAddress isa = (InetSocketAddress)soket.getRemoteSocketAddress();
                            System.out.println("[서버]"+isa.getHostString()+"와 연결 요청 수락");
                            //포트번호는 뭐 별거아닌데, ip주소는 중요한 의미가 있음! 따라서
                            //ip주소는 저장할 필요가 있다. 중요함 서버입장에서
    
    
                            //연결끊기
                            soket.close(); //서버소켓과 마찬가지로 종료해줘야함 단, 서버나 클라이언트 소켓 둘중하나만 끊어도됨
                            System.out.println("[서버]"+isa.getHostName()+"와 연결 끊음");
    
                        }
    
                    } catch (IOException e) {
                        System.out.println(e.getMessage());
                        //소켓익셉션은 io익셉션임
                        //accept() 때문에 있음 서버소켓 종료시
                    }
    
                }
    
            };
            thread.start();
        }
    
        public static void stopServer(){
            try {
                serverSocket.close();
            } catch (IOException e) {
    
            }
        }
    }

    *서버소켓을 생성하고 accept()하는 부분은 쓰레드로 처리해야한다. 이는 서버를 키고 끄는 것과 서버에서 클라이언트 요청 받는 것 동시에 진행되야해서그렇다.

     

     

    - TCP 클라이언트

    Socket socket = new Socket("서버ip",포트번호);
    
    Socket socket = new Socket(new InetAddress.getByName("domainName",포트번호));

    - 연결 요청시 두 가지 예외가 발생할 수 있다. UnknownHostException은 ip 주소나 port번호가 잘못 표기 

    - IOException 제공된 IP와 Port번호로 연결할 수 없을 때 발생

    try{
    Socket socket = new Socket("서버ip",포트번호);
    }catch(UnknownHostException e){
    
    }catch(IOException e){
    
    }

    - 클라이언트 프로그램

    public class TCPClientExam {
    
        public static void main(String[] args) {
            try {
            	//socket 열기 생성동시에 연결요청
                Socket socket = new Socket("localhost",50001);
                System.out.println("[클라이언트]연결성공");
    
              
                //socket닫기
                socket.close();
                System.out.println("[클라이언트] 연결종료");
            } catch (UnknownHostException e) {
                //IP나 포트 표기방법 틀림
                System.out.println("UnknownEx = "+e.toString());
            }catch (IOException e){
                //ip나 포트 없음
                System.out.println("ioEx = "+e.toString());
    
            }
    
        }
    }

     

    > 입출력 스트림으로 데이터 주고 받기 

     

    - 클라이언트 연결 요청을 하고 서버가 연결 요청을 수락했다면, Socket을 통해 입출력 스트림을 얻을 수 있다.

     

    InputStream is = socket.getInputStream();
    OutputStream os = socket.getOutputStream();
    
    //데이터 쓰기 
    S;tring data = "보낼데이터"
    byte[] bytes = data.getBytes("UTF-8");
    os.write(bytes);
    os.flush();
    
    //데이터 쓰기 with DataOutputStream
    DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
    dos.writeUTF(bytes);
    dos.flush();
    
    //데이터 읽기 
    byte[] bytes = new byte[1024];
    int count = is.read(bytes);
    String message =new String(bytes,0,count,"UTF-8");
    //데이터 읽기 with DataInputStream
    DataInputStream dis = new DataInputStream( socket.getInputStream());
    String data = dis.readUTF();

    - 클라이언트 

    try {
            	//..
    
                //데이터보내기 with 일반
                String message = "나는 잡아가 조아";
                byte[] bytes = message.getBytes("UTF-8");
                OutputStream os = socket.getOutputStream();
                os.write(bytes);
                os.flush();
                System.out.println("[클라이언트] 메시지 보냄"+message);
    
                //데이터 받기 with 일반
                InputStream is = socket.getInputStream();
                bytes = new byte[1024];
                int count = is.read(bytes);
                 String recivemessage = new String(bytes,0,count,"UTF-8");
                System.out.println("[클라이언트] 메시지 받음 "+recivemessage);
    			
                //데이터 쓰기 
             //   String message = "나는 잡아가 조아";
             //   DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
             //   dos.writeUTF(message);
             //   dos.flush();
                //데이터 읽기 
               // DataInputStream dis = new DataInputStream(socket.getInputStream());
               // String message = dis.readUTF();
               
               
               //..
                
                }

    -서버 

     						//서버연결
                            //..
                            
                            //데이터 받기 (기본 inputStream)
                            InputStream is = soket.getInputStream();
                            byte[] bytes = new byte[1024];
                            int readByteCount = is.read(bytes);
                            String message = new String(bytes,0,readByteCount,"UTF-8");
    
                            //데이터 보내기(기본 output)
                            OutputStream os = soket.getOutputStream();
                            bytes = message.getBytes("UTF-8");
                            os.write(bytes);
                            os.flush();
                            System.out.println("[서버] 받은 데이터 다시 보냄 "+message);
                            
                            //데이터읽기
                           // DataInputStream dis = new DataInputStream(soket.getInputStream());
                           // String message = dis.readUTF();
                            
                            //데이터보내기
                           // DataOutputStream dos = new DataOutputStream(soket.getOutputStream());
                           // dos.writeUTF(message);
                           // dos.flush();
                            
                            
                            //연결 해제 
                            socket.close();

     

     

    참고자료: 이것이 자바다 (신용권,임경균)

    '언어 > JAVA' 카테고리의 다른 글

    자바스터디(1)  (0) 2023.10.18
    Java - 일급컬렉션  (0) 2023.07.25
    Servlet-JSP MVC07 파일 수정하기  (0) 2023.07.24
    Java - File클래스  (0) 2023.07.24
    스트림(2) - 중간 처리  (0) 2023.07.14
Designed by Tistory.