반응형

** java.net. InetAddress

=>ip정보를 저장하는클래스

=>Static메소드인 HetLocalHost(),getByName(String hostname),getAllByName(String hostname)

getLocalHost():자기 컴퓨터의 ip정보를 리턴

getByName(): hostip정보 1개를 리턴

getAllByName(): host의 모든 ip정보를 리턴

 

**소켓 통신

Socket: NIC(Network Interface Card- LAN Card)를 추상화한 클래스

네트워크 프로그래밍이라는 용어 대신에 Socket Programming이라고도 합니다.

1.통신 방법

1)TCP 프로토콜을 사용하는 스트림 소켓

2)UDP 프로토콜을 사용하는 데이터그램 소켓

 

2.TCP (연결형 통신)

수신하는 쪽에서 송신하는 쪽으로 연결을 요청

송신하는 쪽에서 연결을 하고 요청하는 데이터에 대한 메타 정보(데이터에 대한 정보 - 데이터 크기 등) 를 송신

수신하는 쪽에서 그 정보를 보고 다시 요청을 합니다.

송신하는 쪽에서 데이터를 전송

수신하는 쪽에서 데이터 수신 여부를 송신하는 쪽에 전송하고 통신이 종료

신뢰성이 높지만 트래픽이 증가

http, https TCP통신

 

3.udp(비연결형 통신)

송신하는 쪽에서 수신하는 쪽으로 일방적으로 데이터를 전송하고 통신이 종료

DHCP(IP 동적 할당),DNS(DOmain ->ip)

콜 센터 ,appleapns(apple push Notification Service- 애플 제품의 알림)

수신 쪽에서 데이터를 제대로 받았는지 알 수 없음

public class IPInfo {

       public static void main(String[] args) {

              

               try {

                      //자신의 컴퓨터 ip정보 확인 - 자신의 컴퓨터 이름 (도메인) ip주소

                      InetAddress local = InetAddress.getLocalHost();

                      System.out.println(local);

                      // 구글의 ip장보 학인

                      InetAddress [] googles= InetAddress.getAllByName("www.google.com");

                      for(InetAddress imsi: googles) {

                             System.out.println(imsi);

                      }

               } catch (UnknownHostException e) {

                      System.out.println("예외:" +e.getMessage());

               }

       }

}

 

4Socket 클래스

1)생성자

Socket()

Socket(InetAddress addr, int port): addr port번호에 해당하는 서비스에 접속

Socket(String addr, int port, InetAddress addr, int port ):addrport번호에 접속을 하는데 자신의 주소르 localaddr그리고 portlocalportㄹ 설정해서 접속

 

=>addr이 잘못 되면 NullPointerException 그리고 port번호가 잘못되면 illegalAgumentException이 발생

 

 

2)메소드

void close()

InetAddress getInetAddress():접속된 상대방 ip정보

int getPort():상대방 포트 번호

InputStream getInputStream() 상대방에게서 정보를 읽어오기 위한 스트림

OutputStream getOutputStream() 상대방에게서 정보를 전송하기 위한 스트림

 

 

5. 스트림 소켓 - tcp통신을 위한 소켓

1)수신 받는 쪽의 소켓 생성과 요청

Socket 소켓변수 = new Socket(서버 ip주소 ,포트번호);//연결

//요청 전송

OutputStream 출력스트림 변수 = 소켓변수.getOutputStream();

 

//바이트 단위 전송

출력스트림변수.write(byte[] b);

//문자단위 전송

PrintWriter pw = new PrintWriter(출력스트림변수);

pw.println(String msg);

pw.flush();

 

 

//데이터 읽어오기

InputSteam 입력스트림변수 = 소켓변수.getInputStream();

//바이트 단위로 읽어오기

입력스트림변수 .read(byte[] b);

 

//문자열 단위로 읽어오기

BufferedReader br = new BufferedReader(new InputStreamRader(입력스트림변수));

String msg = br.readLine();//한줄 읽어오기

//null을 리턴할 때 까지 읽으면 전송된 모든 내용을 읽을 수 있습니다.

 

 

6.www.daum.nethtml가져오기

=>www.daum.net이 호스트이름이고 http서버는 기본 포트 번호가 80

 

public class DaumMain {

       public static void main(String[] args) {

               try {

                      //daum 주소를 생성

                      InetAddress addr = InetAddress.getByName("www.daum.net");

                      //TCP 소켓 생성

                      Socket socket = new Socket(addr, 80);

                     

                      //요청 전송

                      PrintWriter pw = new PrintWriter(socket.getOutputStream());

                      pw.println("GET http://www.daum.net");

                      pw.flush();

                     

                      //데이터 읽기 - 문자 단위

                      BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                     

                      //읽을 데이터가 없을 까지 줄단위로 읽ㅇ오기

                      while(true) {

                             String line = br.readLine();

                             if(line == null) {

                                    break;

                             }

                             System.out.println(line);

                      }

                      br.close();

                      socket.close();

               }catch (Exception e) {

                      //예외 메시지 출력

                      System.out.println("예외:" +e.getMessage());

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

7.TCP Server:정보를 제공

=>ServerSocket 사용

1)생성자

ServerSocket()

ServerSocket(int port): port 개방해서 클라이언트의 요청을 받을 있도록 서버가 생성

ServerSocket(int port, int backlog): port 개방해서 클라이언트의 요청을 받을 있도록 서버가 생성되고 최대 접속 개수를 설정

 

2)메소드

void close()

 

Socket accept():호출하면 클라이언트의 요청이 까지 대기 상태가 되고 클라이언트의 요청이 오면 클라이언트와 통신할 있는 Socket 리턴하고 다음으로 넘어갑니다.

 

3)통신과정

=>ServerSocket 생성해서 클라이언트의 요청을 기다림

=>클라이언트 쪽에서 Socket 이용해서 서버에 접속

=>Socket 스트림을 가지고 메시지를 전송

=>ServerScoket 생성할 port 사용 중이 아닌 번호로 설정 -1024보다 숫자로 설정하는 것을 권장

서버 소켓을 생성하고 예외가 발생해서 프로그램이 중단되면 이전에 사용한 포트번호를 사용하지 못할 있습니다.

자바로 실행 중인 프로세스를 찾아서 중단해야 이전 포트를 다시 사용 가능합니다.

=>현재 사용 중인 포트를 확인:netstat - ano

자신의 ip확인 :ipconfig / (config -mac)

=>다른 컴퓨터에서 자신의 컴퓨터에 접속하도록 할려면 방화벽 해제 되어 있어야 합니다.

 

public class TCPServer {

       public static void main(String[] args) {

               try {

                      //서버 소켓을 생성

                      ServerSocket ss = new ServerSocket(9000);

                      while(true) {

                             System.out.println("서버 대기  ...");

                             //클라이언트의 접속을 기다림

                             Socket socket = ss.accept();

                             //접속한 클라이언트 정보 확인

                             System.out.println("접속한 클라이언트 : " +socket.getInetAddress());

                             //클라이언트가 전송한 메시지 확인

                             BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                             String msg = br.readLine();

                             System.out.println("메시지:" +msg);

                            

                             //클라이언트에게 메시지 전송

                             PrintWriter pw= new PrintWriter(socket.getOutputStream());

                             pw.println("서버가 보내는 메시지");

                             pw.flush();

                            

                             br.close();

                             pw.close();

                             socket.close();

                      }

               }catch (Exception e) {

                      //예외 메시지 출력

                      System.out.println("예외:" +e.getMessage());

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

public class TCPClinet {

       public static void main(String[] args) {

               try {

                      //서버에 접속하는 소켓을 생성 - 127.0.0.1

                      Socket socket = new Socket(InetAddress.getByName("ip주소") , 9000);

                      //메시지 전송

                      Scanner sc = new Scanner(System.in);

                      System.out.print("전송할 메시지:");

                      String msg = sc.nextLine();

                      PrintWriter pw= new PrintWriter(socket.getOutputStream());

                      pw.println(msg);

                      pw.flush();

                     

                      //메시지 읽기

                      BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                      String str = br.readLine();

                      System.out.println(str);

                     

                      br.close();

                      pw.close();

                      socket.close();

               }catch (Exception e) {

                      //예외 메시지 출력

                      System.out.println("예외:" +e.getMessage());

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

8.UDP

=>비연결형 통신

=>보내는 쪽에서 받는 쪽으로 메시지만 전송하고 통신이 종료

1)통신방식

unicast:1:1로 통신하는 방식

multicast:그룹에 속한 모든 클라이언트와 통신

 

broadcast:자신이 ip대역과 subnet mask를 이용해서 자신의 ip대역과 같은 그룹에 속한 모든 클라이언트에게 전소

 

 

2)DatagramPacket클래스와 DataGramSocket클래스 이용

=>DataGramSocket클래스

생성자

DataGramSocket(): 전송을 하기 위한 소켓

DataGramSocket(int socket):전송을 받기 위한 소켓

 

메소드

void close();

void recieve(DatagramPacket packet): 데이터를 받는 메소드

void sen(DatagramPacket packet): 데이터를 보내는 메소드

 

 

=>DatagramPacket클래스

생성자

DatagramPacket(byte [] bif, int length):전송을 받기 위한 패킷으로 byte배열에 데이터가 저장됩니다.

DatagramPacket(byte [] bif, int length, InetAddress addr, int port) :전송을 하기 위한 패킷으로 byte 배열의 내용을 length만큼 addrport에게 전송하기 위한 패킷

 

메소드

byte[] getData(): 데이터 리턴

int getLength():길이 리턴

 

=>String byte배열 변환

String ->byte배열 :String.getBytes();

byte배열 ->String : new String(byte배열)

public class UDPReceive {

       public static void main(String[] args) {

               try {

                      //받는 소켓을 생성

                      DatagramSocket socket = new DatagramSocket(7777);

                     

                      //데이터를 저장할 패킷을 생성

                      //byte[] b = new byte[65536];

                      //DatagramPacket dp = new DatagramPacket(b, b.length);

                      //데이터를 전송받아서 읽기

                      while(true) {

                            

                             //데이터를 저장할 패킷을 생성

                             // 두개의 문장을 반복문 바깥에 만들면 통신은 되는데 메시지를 보내고 짧은 메시지를 보내면

                             //짧은 메시지 뒤에 메시지의 내용이 추가되는 형태가 됩니다.

                             //반복문 안에서 계속 사용해야 하는 데이터는 반복문에서 초기화를 해주어야 합니다.

                             byte[] b = new byte[65536];

                             DatagramPacket dp = new DatagramPacket(b, b.length);

                            

                             //대기하고 있다가 데이터를 전송받으면 동작

                             socket.receive(dp);

                             //보낸곳 확인

                             System.out.println("보낸 :" +dp.getAddress().getHostAddress());

                             //데이터 확인

                            

                             String msg = new String(b);

                             System.out.println(msg);

                            

                      }

               }catch (Exception e) {

                      //예외 메시지 출력

                      System.out.println("예외:" +e.getMessage());

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

 

public class UDPSend {

       public static void main(String[] args) {

               try {

                      // udp전송을 위한 소켓 생성

                      DatagramSocket ds = new DatagramSocket();

                      Scanner sc = new Scanner(System.in);

                      while(true) {

                             //메시지 입력

                             System.out.print("전송할 메시지:");

                             String msg = sc.nextLine();

                            

                             //전송할 패킷 생성

                             DatagramPacket dp = new DatagramPacket(msg.getBytes(), msg.getBytes().length,InetAddress.getByName("127.0.0.1"),7777);

                             ds.send(dp);

                            

                             //sc.close();

                             //ds.close();

                      }

               } catch (Exception e) {

                      // 예외 메시지 출력

                      System.out.println("예외:" + e.getMessage());

                      // 예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

 

4)multicast

=>그룹에 속한 모든 단말에게 데이터를 전송하는 방식

=>244.0.0.0 ~ 239.255.255.255사이의 주소를 이용

이 주소 대역은  D class대역으로 Multicast용으로 예약된 ip주소 대역

=>MulticastScoket을 이용해서 구현

 

=>생성자

MulticastScocket();

MulticasetSocket(int port):

 

=>메소드

joinGroup(InetAddress addr) :그룹에 참여

leaveGroup(InetAddress addr):  그룹에서 빠져나오는 메소드

 

=>데이터 전송방식은 DatagramScocket과 동일

 

=>multicast 받는 쪽

 

public class MultiReceive {

       public static void main(String[] args) {

               try {

                      MulticastSocket ms = new MulticastSocket(9999);

                      //멀티케스트에 참여

                      //224.0.0.0 to 239.255.255.255

                      ms.joinGroup(InetAddress.getByName("ip주소"));

                      System.out.println("멀티 케스트 시작");

                     

                      while(true) {

                             //전송 받은 데이터를 저장할 바이트 배열 - 크기는 8 배수로 설정

                             byte [] b = new byte[65536];

                             //패킷을 생성

                             DatagramPacket dp = new DatagramPacket(b, b.length);

                             //데이터를 받을 있도록 대기

                             ms.receive(dp);

                            

                             //데이터 읽기

                             String msg = new String(dp.getData());

                             System.out.println(ms);

                      }

                     

               }catch (Exception e) {

                      //예외 메시지 출력

                      System.out.println("예외:" +e.getMessage());

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

 

=>multicast 보내는 쪽

public class MultiSend {

       public static void main(String[] args) {

               try {

                      MulticastSocket ms = new MulticastSocket();

                      Scanner sc = new Scanner(System.in);

                     

                      System.out.print("닉네임:");

                      String nickname = sc.nextLine();

                      while(true) {

                             System.out.print("전송할 메시지(종료는 end):");

                             String msg = sc.nextLine();

                             //자바에서 문자열은 == 비교하면 참조를 비교

                             //equals 비교해야 값을 비교

                             if(msg.equals("end")) {

                                    System.out.println("종료");

                                    break;

                             }

                             msg = nickname +" : "+ msg;

                             DatagramPacket dp =  new DatagramPacket(msg.getBytes(), msg.getBytes().length,InetAddress.getByName("ip주소"),9999);

                             ms.send(dp);

                      }

               } catch (Exception e) {

                      // 예외 메시지 출력

                      System.out.println("예외:" + e.getMessage());

                      // 예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

=>채팅 처럼 동시에 주고 받는 것이 가능하도록 할려면 보내고 받는 로직을 스레드를 이용해서 작업

콘솔에서는 쉽지 않습니다.

입력창과 출력창이 같아서 콘솔을 채팅은 동시에 입출력 한계가 있습니다.

 

 

**url 통신

=>소켓 통신을 저수준의 통신방식이라고 하고 그 이외의 통신 방식들은 고수준이라고 부릅니다.

성능은 소켓 통신이 우수한데 소켓 통신은 프로그램을 별도로 설치해야만 통신이 가능합니다.

url 통시은 브라우저를 통해서 사용이 가능하고 현재는 거의 모든 운영체제가 웹 브라우저를 하나씩 가지고 있습니다.

소켓 통신 : 증권 , 게임 등 주식거래는 조금한 시간의 차가 경제적으로 문제가 발생할 수 있다. 빨리 해야 한다.

최근에는 웹에서도 소켓 방식의 통신이 가능합니다.

WebSocket APIHTML5에서 제공

 

=>ULR 구성

프로토콜 : // 도메인이나 IP :포트번호 /파일 경로?이름=&이름=...

프포토콜과 도메인은 생략 못함

포트번호는 서비스의 기본포트를 사용하는 경우에는 생략이 가능

http:80, https:443

파일경로를 생략하는 경우가 있는데 이 경우는 서버의 설정을 이용해서 파일을 찾아옵니다.

 

파일 경로 뒤에 ? parameter라고 하는데 클라이언트가 서버에게 넘겨주는 데이터로 key-value형식으로 대입

parameter 전송 방식을 가지고 get방식과 post 방식을 구분

 

파일 경로 뒤에 #이 붙는 경우는 책갈피 입니다.

페이지 내엣 이동

 

1.java.net.URL클래스

=>URL을 만들기 위한 클래스

1)생성

URL(String url)

=>없는 url을 대입하면 MalformedURLException이 발생

 

2)메소드

URLConnection openConnection():URL과 양방향 통신이 가능한 Connection 을 리턴

여기서 리턴한 Connection HttpURLConnection이나 JarURLConnection으로 형변환해서 사용해야 합니ㅏㄷ.

 

URLConnection은 추상 클래스라서 메소드가 구현되어 있지 않습니다.

 

2.HttpURLConnection

=>URL 통신을 하기 위한 클래스

=>URL 클래스의 openConnection메소드를 이용해서 생성

=>메소드

setConnectTimeout(int timeout):밀리초 단위로 타입아웃을 설정하는 메소드로 타임 아웃 동안 접속이 안되면 접속 실패

 

setUseCaches(boolean isCache):이전에 접속했던 URL에 다시 요청할 때 이전 데이터를 가져올 것인지 설정 자주 변경되는 URL의 데이터는 반드시 false로 설정을 해주어야 합니다.

 

 

setRequestProperty(String field, String value)

addRequestProperty(String field, String value)

헤더에 값을 추가하는 메소드

카카오는 헤더에 추가해야 된다.

 

setRequestMethod(String method): 전송 방식을 설정

 

int getResponseCode():서버로 부터의 상태를 리턴

200번대 정상응답

300번대 리다이렉트 중

400번대 클라이언트 오류( 404- 잘못된 url)

500번대 서버 오류

 

InputStream getInputStream(): 데이터를 읽기 위한 스트림 리턴

 

3.웹의 데이터 포맷

xml: 태그 형식으로 표현하는 포맷, 별도의 라이브러리 없이 파싱 가능

JSON: 자바스크립트 객체 표현 방법으로 데이터를 표현, 별도의 라이브러리를 추가해야 파싱 가능

 

CSV: 구분자가 있는 문자열

HTML: 뷰의 용도로 사용되는 포맷인데 사이트에서 XML이나 JSON형태로 데이터를 제공해주지 않아서 수집해서 사용

 

 

4.OPEN API

데이터를 가진 곳에서 일반 사용자들에게 데이터를 사용할 수 있도록 XML이나 JSON형식으로 제공하는 것 데이터 뿐 아니라 라이브러리나 프레임워크 등을 제공하기도 함

 

데이터는 대부분의 경우 가입을 해서 키를 받는 형태로 제공

키 값을 주소에 넣기도 하고 헤더에 하는 방법

 

http://data.go.kr/

 

 

5.동기적 다운로드

public class StringDownload {

       public static void main(String[] args) {

               try {

                      //다운로드 받을 url 생성

                      URL url= new URL("https://www.naver.com");

                      //url연결 객체 생성

                       HttpURLConnection con = (HttpURLConnection)url.openConnection();

                       //연결 옵션 설정

                       con.setConnectTimeout(30000); //30 동안 연력이 안되면 연결시도 종료

                       //캐시 사용을 하지 않음

                       con.setUseCaches(false);

                       

                       //데이터를 읽어올 스트림을 생성

                       BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                       //많은 양의 문자열을 읽어야 하는 경우

                       StringBuilder sb = new StringBuilder();

                       while(true) {

                              // 읽기

                              String line = br.readLine();

                              //읽은 데이터가 없으면 반복은 중단

                              if(line == null) {

                                     break;

                              }

                              //데이터가 있으며면 sb 추가

                              sb.append(line+"\n");//메모리 낭비가 줄어들 있다.

                       }

                       //StringBuilder 데이터를 STring 으로 변환

                       String msg = sb.toString();

                       System.out.println(msg);

               }catch (Exception e) {

                      //예외 메시지 출력

                      System.out.println("예외:" +e.getMessage());

                      //예외가 발생한 코드를 역추적

                      e.printStackTrace();

               }

       }

}

 

 

6.비동기 다운로드

=>위처럼 스레드를 사용하지 않고 다운로드 받는 방식을 동기식이라고 합니다.

동기식은 데이터를 다운로드 받는 동안 다른 작업을 할 수 없습니다.

데이터 다운로드와 관련없는 작업도 데이터를 다운로드 동안은 수행할 수 없습니다.

네트워크 작업은 스레드를 이용해서 비동기식으로 동작하도록 만드는 것을 권장(안드로이드는 필수)

다운로드와 관련없는 작업은 다운로드 받는 동안 수행되도록 작성한는 것이 좋습니다.

 

public class ImageDownload {

       public static void main(String[] args) {

               Thread th = new Thread() {

                      public void run() {

                             try {

                                    String addr = "https://img0.yna.co.kr/photo/yna/YH/2019/04/07/PYH2019040703010000700_P4.jpg";

                                    //파일명을 만들기 위해서 마지막/ 다음의 문자열 가져오기

                                    int len = addr.lastIndexOf("/");

                                    String filename =addr.substring(len+1);

                                    System.out.println(filename);

                                    //현제 디렉토리에 파일이 있으면 있다고 출력하고 없다면 다운로드 받아서 저장

                                    File f = new File("./"+filename);

                                    if(f.exists() == true) {

                                           System.out.println("파일이 이미 존재합니다.");

                                            return;

                                    }else {

                                            //한번에 읽어오기

                                            /*

                                            URL url = new URL(addr);

                                            HttpURLConnection con = (HttpURLConnection)url.openConnection();

                                           con.setConnectTimeout(30000);

                                           con.setUseCaches(false);

                                           

                                            //다운로드 받을 파일의 킈를 가져오기

                                            int length = con.getContentLength();

                                            //데이터 저장할 바이트 생성

                                            byte [] b = new byte[length];

                                            //바아트 단위로 데이터를 읽어옴 스트램 생성

                                           BufferedInputStream bis = new BufferedInputStream(con.getInputStream());

                                            //대이터틀 읽어서 b 저장

                                            bis.read(b);

                                            //읽어온 내용을 파일제 저장

                                            PrintStream ps = new PrintStream(new FileOutputStream("./src/java/"+filename));

                                            ps.write(b);

                                           

                                            //사용한 스트럼 닫기

                                            ps.close();

                                            bis.close();

                                            //연결 끝ㅎ기

                                            con.disconnect();

                                             */

                                           

                                            URL url = new URL(addr);

                                            HttpURLConnection con = (HttpURLConnection)url.openConnection();

                                           con.setConnectTimeout(30000);

                                           con.setUseCaches(false);

                                           

                                            //데이터 저장할 바이트 생성

                                           BufferedInputStream bis = new BufferedInputStream(con.getInputStream());

                                            //읽어온 내용을 파일제 저장

                                            PrintStream ps = new PrintStream(new FileOutputStream("./src/java/"+filename));

                                           

                                           while(true) {

                                                   //size 바이트 배열

                                                   byte [] b= new byte[512];

                                                   //내요을 읽어서 b 저장하고

                                                   //읽은 개수를 r 저장

                                                   int r = bis.read(b);

                                                   //읽은개 없으면 중닺ㄴ

                                                   if(r<= 0) {

                                                          break;

                                                   }

                                                   ///읽은 데이터가 있으면 기록

                                                   ps.write(b,0,r);

                                                   //버퍼에 내용이 남아있는 것을 방지하기 위해서 마지막에 flush 호출

                                                   ps.flush();

                                            }

                                           

                                            //사용한 스트럼 닫기

                                            ps.close();

                                            bis.close();

                                            //연결 끝ㅎ기

                                            con.disconnect();

                                           

                                    }

                             }catch(Exception e) {

                                    System.out.println("다운로드 예외:" + e.getMessage());

                                    e.printStackTrace();

                             }

                      }

               };

               th.start();

              

               //스레드 동작 쉬는 시간이 생기면 동작

               System.out.println("스레드와 상관없는 코드");

       }

}

 

 

**XML Parsing

=>RSS(Really Simple Syndication,Rich Site Summary): 빠른 속도로 변경되는 데이터를 제공하기 위한 서비스로 예전에는 xml 을 많이 사용

=>xml: 태그 형식으로 표현하는 데이터 포맷

xml으 해석은 xml상단에 dtd가 있으면 dtd가 하고 없으면 개발자가 해석

=>html은 브라우저가 해석하기 때문에 우리가 원하는 내용만 고라서 보는게 안되고 출력을 직접 하게 되면 화면 크기에 따라 원하는 모양으로 볼 수가 없습니다.

데이터를 제공해서 보고자 하는 쪽에서 원하는 것만 골라서 원하는 크기로 볼 수 있도록 해줍니다.

 

 

1.xml Parsing

=>DOM(Documnet Object Model) Parser 이용

내용을 메모리에 트리 형태로 전부 펼쳐 놓고 원하는 데이터를 찾아가는 방식

 

DocumentBuilderFactory factory  = DocumentBuilderFactory.newInstance();

DocumentBuilder bulder = factory.newDocumentBuilder():

Document document = builder.parse(String uri);

//uri 대신에 inputStream inputStream, FIle file을 대입해도 됩니다.

//Dom의 형태로 메모리에 펼칩니다.

 

//루트 찾기

Element root = document.getDocumentElement();

 

//원하는 태그 찾아오기

NodeList list = root.getElementsByTagName(String tag);

s->전체 가져오기 s없으면 하나 가져오기

//위에서 찾은 list를 가지고 반복문을 수행

int n = list.getLength();

for (int i = 0; i< n ; i++){

           Node item = list.item(i);

           Node text = item.getFirstChild();

           text.getNodeValue();//태그 안의 내용

}

 

 

 

=>http://hani.co.kr/arti/sports/sports_general/ :한겨래 스포츠 rss

위 주소에서 titlelink만 추출해서 출력

 

thread.sleep() 하면서 하면 된다.

기상층도 xml로 준다.

 

**java에서의 외부 라이브러리 사용

=>일반 java applicationjar(java압축파일)파일을 build path에 추가

=>java web applicationWEB-INF/lib 디렉토리에 jar파일을 복사

=>maver이나 gradle기반의 프로젝트는 설정 파일에 의존성을 설정

=>자바 라이브러리는 www.mvnrepository.com에서 다운로드 기능

 

 

 

 

**json parsing

1.JSON

=>자바 스크립트 객체 표현법으로 데이터를 표현

파이썬의 리스트와 DIC 표현법과도 동일

{"key":"value" ,"key":"value" ...}:객체

["data1","data2" ...]:배열

 

2.파싱을 할려면 외부 라이브러리 이용

1) www.mvnrepository.com에서 json을 검색

 

자바는 jar,war 은 자기가 풀수 있다.

python zip , tar은 자기가 풀수 있다.

 

2)다운로드한 파일을 프로젝트에 복사

 

3) 복사한 파일을 선택하고 마우스 오르쪽을 클릭해서 [Build Path]-[Add to Build Path]를 클릭

Build Path에 추가하면 실행할 때 이 파일에 있는 클래스 들을 jvm이 로드를 사용할 수 있도록 해줍니다.

 

3.파싱

1)JSONObject

=>객체를 가져올 때 사용하는 자료형

 

2)JSONArray

=>배열을 가져올 때 사용하는 자료형

 

3)파싱과정

문자열을 가지고 new JSONObject(String json)(중괄호)이나 new JSONArray(String json)(대괄호)을 호출해서 객체나 배열 생성

 

JSONObjectget자료형(String key):key 에 해당하는 데이터를 자료형으로 리턴

JSONArrayget자료형(int index): index에 해당하는 데이터를 자료형으로 리턴, 배열은 개수를 length메소드로 리턴

 

4) kakap open api사용

=>최근의 open api들은 인증키를 url에 포함시키지 않고 header에 포함시켜서 요청하도록 합니다.

=>developer.kakao.com에서 open api데이터 사용을 신청

developer.kakao.com여기에서 자기 아이디로 등록하기

 

네이티브 앱 키

REST API ->open api

JavaScript ->web

Admin

·       네이티브 앱 키: iOS, Android 앱 개발시 필요한 key

·       REST API : REST API 호출시 필요한 key

·       Javascript : Javascript 앱 개발시 필요한 key

·       Admin : Push, 앱관리 등 관리자 권한에서 필요한 key. 보안 유지 필수

 

 

자기가 어떤것으로 사용할 것인지 설정을 하셔야 합니다.

하루에 몇개 만큼 쓸 것인가?

 

도서 검색

"https://dapi.kakao.com/v3/search/book?target=title&query=검색할 도서명  

Header Authorization: KakaoAK kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk

                             (자신의 REST API 키 사용한다.)

 

 

 url은 받느시 인코딩을 해줘어야 합니다.

한글이 있으면 utf-8로 변환해서 대입해야 합니다.

java.net.Encode.encode(String str,String enctype);

java.net.Encode.encode("미움받을 용기","utf-8");

 

?뒤에 들어가는 데이터를 parameter라고 하는데 이름=&이름=..의 형태

파라미터는 순서가 없기 때문에 아무거나 먼저 입력해도 됩니다.

 

 

4.kakao 의 도서검색 api파싱

 

https://developers.kakao.com/docs/restapi/search#%EC%B1%85-%EA%B2%80%EC%83%89

참조해서 해야 한다.

 

json object ->meta

json array ->documents

 

utf-8 UTF8같다.

CP949 = MS949같다.

EUCKR euc-kr

 

 

public class KakaoOpenAPI {

       public static void main(String[] args) {

               //데이터를 다운로드 받는 부분

               String json = null;

               try {

                      //검색함 도서이름 거입력

                      System.out.print("검색함 도서명:");

                      Scanner sc = new Scanner(System.in);

                      String book = sc.nextLine();

                     

                      //book 한글로 입력할 있으므로 인코딩

                      book =URLEncoder.encode(book,"utf-8");

                      //다운 로드 받을 url생성

                      //항상 인코딩을 해야 한다. 아니면 조회가 안된다.

                      //입력 받는 것은 뒤에 하는것이 좋다.

                      URL url = new URL("https://dapi.kakao.com/v3/search/book?size=50&page=2&sort=latest&target=title&query="+book);

                     

                      //연결 객체 생성

                      HttpURLConnection con =(HttpURLConnection)url.openConnection();

                      //옵션 설정

                      con.setConnectTimeout(20000);

                      con.setUseCaches(false);

                     

                      con.addRequestProperty("Authorization", "자신의 REST API 키 사용한다");

                     

                      //문자열 읽어오기

                      BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));

                      StringBuilder sb = new StringBuilder();

                      while(true) {

                             String line = br.readLine();

                             if(line == null) {

                                    break;

                             }

                             sb.append(line+"\n");

                      }

                      //데이터를 문자열로 변환

                      json = sb.toString();

                     

                      br.close();

                      con.disconnect();

                      sc.close();

                     

                      //System.out.println(json);

               }catch (Exception e) {

                      System.out.println("다운로드 에러:" +e.getMessage());

                      e.printStackTrace();

               }

               //데이터를 파싱하는  부분

               if(json == null) {

                      System.out.println("읽어온 데이터가 없습니다.");

               }else {

                      //전체 문자열을 json 객체로 변환

                      JSONObject root = new JSONObject(json);

                      //System.out.println(root);

                      //meta 객체

                      JSONObject meta = root.getJSONObject("meta");

                      //System.out.println(meta);

                      //documents 배열

                      JSONArray documents = root.getJSONArray("documents");

                      //System.out.println(documnets);

                     

                      //배열의 데이터 개수 찾아오기

                      int len = documents.length();

                      for(int i = 0; i <len; i++) {

                             JSONObject document = documents.getJSONObject(i);

                             //System.out.println(documnet);

                             try {                       

                                    String title = document.getString("title");

                                    int price = document.getInt("price");

                                   

                                    //thumbnail

                                    String thumbnail = document.getString("thumbnail");

                                    //인코딩은 문자열을 메모리에 저장되는 코드로 변환하는 것이고

                                    //디코딩은 메모리에 저장된 코드를 원래의 문자열로 복원하는 것입니다.

                                    System.out.println(title+" : "+price+" "+URLDecoder.decode(thumbnail,"utf-8"));

                             }catch(Exception e) {}

                      }

               }

       }

}

 

 

**HTML 파싱

=>사이트에서 출력은 되어 있는데 Open API형태로 데이터를 제공하지 않는 경우 HTML을 읽어서 사용

twitteropen api있는 지 확인하고 없으면 html가져와서 해야 한다.

=>HTML가져올 때는 URL의 인코딩에 주의하고 읽어온 데이터의 인코딩에도 주의

읽어온 데이터나 싸이트 등 설정해야 한다.

=>읽어야 하는 데이터가 AJAX(비동기적으로 데이터 가져오는 기술)형태로 만들어져 있거나 로그인을 해야하는 경우 또는 자바스크립트 코드를 실행해야 하는 경우에는 selenium같은 라이브러리를 사용해야 합니다.

로그인을 해야 하는 경우도 있고 부모 경로로 가는 경우 도 잇다.

HTTPURL 스코롤 한 것은 나오지 않는다.

=>자바에서 HTML파싱에 많이 이용되는 라이버러리는 JSoup

 

 

tag :중복 될 수 있습니다. (여러개 가능하다.)

id :중복 될 수 없습니다. -개발자가 만든 것이라서 없는 태그도 있습니다.(없을 수 있다.)

class : 중복 될 수 있습니다.

xpath:중복 될 수 없습니다. -태그의 경로라서 개발자가 만드는 것이 아니고 브라우저가 위치를 찾는 개념

(이것은 무조건 있다.)

 

selector: dom객체를 선택하기 위한 문법

로그인은 xpath찾는 것이 좋다.chrom 검사할 경우 선태하실때 오른쪽 눌르시면 copy가보면 selector xpath가 있다.

xpath는 네이브 자동로그인 할 경우

 

 

 

 

반응형

'Study > Java' 카테고리의 다른 글

java-17  (0) 2020.10.10
java-16  (0) 2020.10.10
java-14  (0) 2020.10.04
java-13  (0) 2020.10.03
java-12  (0) 2020.10.02

+ Recent posts