일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- scanner
- 힙덤프
- List
- map
- javascript
- dfs
- 리소스모니터링
- Java
- 스프링부트
- 큐
- set
- spring boot
- math
- alter
- sql
- JPA
- deque
- html
- priority_queue
- 스택
- NIO
- string
- union_find
- BFS
- CSS
- Union-find
- GC로그수집
- date
- Properties
- Calendar
- Today
- Total
매일 조금씩
12/04 - JDBC(2) : CRUD, 네트워크(URL, URLConnection), TCP네트워킹(ServerSocket, Socket) 본문
12/04 - JDBC(2) : CRUD, 네트워크(URL, URLConnection), TCP네트워킹(ServerSocket, Socket)
mezo 2020. 12. 5. 21:07* CRUD - 어플리케이션(DML)
Java program
-> JDBC APIs
java.sql.*
-> JDBC driver
Connection
Statement / PreparedStatement
ResultSet
* DatabaseMetaData / ResultSetMetaData
* 각 데이터베이스 제작업체(벤더)
mariadb - mariadb 사이트
mysql, oracle - oracle 사이트
mssql - microsoft 사이트
-> DBMS
-> 파일
어제 한 작업들을 CRUD(Create Read Update Delete)라고 한다. (어플리케이션을 만드는 작업)
오늘은 어제 한 CRUD 작업을 메서드화하고 클라이언트와 서버를 따로 만들어서 데이트베이스와 연결 구동까지 해볼거다.
1. CRUD 작업의 메서드화
주소들이 담겨있는 텍스트 파일에서 입력받은 동이름에 해당하는 주소들을 긁어오게 할 것이다.
필요한 메서드는 두가지이다.
- 입력 메서드 : 동이름을 입력받기 위한 메서드이다. 입력받은 동이름을 리턴한다.
- 데이터베이스 처리용 메서드 : 데이터베이스에 접속해서 입력받은 동이름과 일치하는 주소들을 가져온다.
1) 메서드 만들기
- 입력 메서드 - inputDong()
- 데이터베이스 처리용 메서드 - searchDont(String strDong)
2) try~catch를 메서드 안에서 안하고 메서드가 예외를 thows 해서 main안에서 try~catch 구현한다.
메서드 안에서 close()까진 해줘야한다.
3) println은 메서드 안에서는 잘 안쓴다.
따라서 데이터들을 메서드에서 출력안하고 ArrayList<String>으로 리턴하게 해서 main에서 출력한다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class SearchZipcodeEx02 {
// 1. 입력 메서드
// 2. 데이터베이스 처리용 메서드
// 입력 메서드 - 입력받은 문자열을 리턴 (try~catch)
/*
public String inputDong() {
BufferedReader br = null;
String strDong = "";
try {
br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("동이름 입력 : ");
strDong = br.readLine();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (br != null)try { br.close();} catch(IOException e) {}
}
return strDong;
}
*/
// 입력 메서드 - 입력받은 문자열을 리턴 (위임 - throws / 호출하는 쪽(main)에서 예외처리 해줌)
public String inputDong() throws IOException{
BufferedReader br = null;
String strDong = "";
br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("동이름 입력 : ");
strDong = br.readLine();
if (br != null) { br.close();}
return strDong;
}
// 데이터베이스 처리용 메서드
public ArrayList<String> searchDong(String strDong) throws ClassNotFoundException, SQLException{
String url = "jdbc:mysql://localhost:3307/sample";
String user = "root";
String password = "!123456";
Class.forName("org.mariadb.jdbc.Driver");
Connection conn = DriverManager.getConnection(url, user, password);
String sql = "select zipcode, sido, gugun, dong, ri, bunji from zipcode where dong like ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
// pstmt.setString(1, strDong + "%");
ResultSet rs = pstmt.executeQuery();
ArrayList<String> datas = new ArrayList<String>();
while(rs.next()) {
// System.out.println(rs.getNString("zipcode"));
String data = String.format("[%s] %s %s %s %s %s"
,rs.getNString("zipcode")
,rs.getNString("sido")
,rs.getNString("gugun")
,rs.getNString("dong")
,rs.getNString("ri")
,rs.getNString("bunji"));
datas.add(data);
}
if(rs != null)rs.close();
if(pstmt != null)pstmt.close();
if(conn != null)conn.close();
return datas;
}
public static void main(String[] args) {
// ** 호출만 함
// 객체 생성
SearchZipcodeEx02 sz = new SearchZipcodeEx02();
// 메서드 예외처리 위임 구현
try {
// 입출력 메서드
String strDong = sz.inputDong();
// 데이터베이스 처리용 메서드
ArrayList<String> datas = sz.searchDong(strDong);
for(String data: datas) {
System.out.println(data);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch(SQLException e) {
e.printStackTrace();
}
}
}
2. DAO, DTO
CRUD 를 메서드화 했다면 이 메서드화한 것들을 별도의 클래스로 정의할 수 있을 것이다. 그 클래스들은 데이터 베이스와 관련된 작업을 하는 클래스가 될것이다. 이런 데이터베이스 관련 클래스의 종류는 2가지가 있다.
- DAO(Data Access Object) : Database에 접근하기 위한 객체
- DTO(Data Transfer Object)(= VO(Value Object)) : 계층간 데이터 교환을 위한 자바빈즈. getter, setter메소드 가짐
>> DAO ?
웹서버는 DB와 연결하기 위해서 매번 커넥션 객체를 생성하는데, 이것을 해결하기 위해 나온것이 컨넥션 풀이다. ConnectionPool 이란 connection 객체를 미리 만들어 놓고 그것을 가져다 쓰는 것이다. 또 다쓰고 난 후에는 반환해 놓는 것. 하지만 유저 한명이 접속해서 한번에 하나의 커넥션만 일으키지 않고 게시판 하나만 봐도 목록볼때 한번, 글읽을때마다 한번, 글쓸때 한번 등등… 엄청나게 많은 커넥션이 일어나기에, 커넥션풀은 커넥션을 또 만드는 오버헤드를 효율적으로 하기 위해 DB에 접속하는 객체를 전용으로 하나만 만들고, 모든 페이지에서 그 객체를 호출해다 사용한다면? 이렇게 커넥션을 하나만 가져오고 그 커넥션을 가져온 객체가 모든 DB와의 연결을 하는것이 바로 DAO 객체다.
DAO(Data Access Object)는 DB를 사용해 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 오브젝트를 말한다.
>> DTO ?
여기서 말하는 계층간의 Controller, View, Business Layer, Persistent Layer를 말하며 각 계층간 데이터 교환을 위한 객체를 DTO 또는 VO라고 부른다. 그런데 VO는 DTO와 동일한 개념이지만 read only 속성을 가진다.
일반적인 DTO는 로직을 갖고 있지 않는 순수한 데이터 객체이며 속성과 그 속성에 접근하기 위한 getter, setter 메소드만 가진 클래스를 말한다.
실습1) DAO, DTO 구현
(1) DAO
실행 객체로서 전달객체인 ZipcodeTO를 생성한다.
ZipcodeDAO() - 생성자로서 데이터베이스에 접속하는 메서드로 정의한다.
searchZipcode(String strDong) - 동이름과 함께 호출되는 메서드는 ZipcodeTO 객체를 생성하여 결과값을 ArrayList<ZipcodeTO>에 담아 리턴한다.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class ZipcodeDAO {
private Connection conn = null;
// 생성자
// 데이터베이스 접속
public ZipcodeDAO() throws ClassNotFoundException, SQLException{
String url = "jdbc:mysql://localhost:3307/sample";
String user = "root";
String password = "!123456";
Class.forName("org.mariadb.jdbc.Driver");
this.conn = DriverManager.getConnection(url, user, password);
// Connection conn = DriverManager.getConnection(url, user, password);
}
// SQL 구문별 메소드 - 동이름과 함께 호출되는 메서드는 그 결과값을 ArrayList<String>으로 리턴
public ArrayList<ZipcodeTO> searchZipcode(String strDong) throws ClassNotFoundException, SQLException{
ArrayList<ZipcodeTO> datas = new ArrayList<ZipcodeTO>();
String sql = "select zipcode, sido, gugun, dong, ri, bunji, seq from zipcode where dong like ?";
//
PreparedStatement pstmt = this.conn.prepareStatement(sql);
pstmt.setString(1, strDong + "%");
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
String zipcode = rs.getNString("zipcode");
String sido = rs.getNString("sido");
String gugun = rs.getNString("gugun");
String dong = rs.getNString("dong");
String ri = rs.getNString("ri");
String bunji = rs.getNString("bunji");
String seq = rs.getNString("seq");
ZipcodeTO to = new ZipcodeTO(zipcode, sido, gugun, dong, ri, bunji, seq);
datas.add(to);
}
return datas;
}
}
(2) DTO
전달 객체로서 ZipcodeDAO 에서 호출된다.
ZipcodeTO() - 생성자로서 ZipcodeDAO의 searchZipcode(String strDong) 메서드에서 컬럼을 인자값으로 받아 setter역할을 수행하면서 객체를 생성한다. 나머지 getter들은 main 함수에서 값을 출력 할 때 사용한다.
public class ZipcodeTO{
// table의 칼럼
// select문의 컬럼
// DAO로 받아온 값들을 조작할 수 있게 선언
private String zipcode;
private String sido;
private String gugun;
private String dong;
private String ri;
private String bunji;
private String seq;
// 생성자 - setter
public ZipcodeTO(String zipcode, String sido, String gugun, String dong, String ri, String bunji, String seq){
this.zipcode = zipcode;
this.sido = sido;
this.gugun = gugun;
this.dong = dong;
this.ri = ri;
this.bunji = bunji;
this.seq = seq;
}
// getter
public String getZipcode() {
return zipcode;
}
public String getSido() {
return sido;
}
public String getGugun() {
return gugun;
}
public String getDong() {
return dong;
}
public String getRi() {
return ri;
}
public String getBunji() {
return bunji;
}
public String getSeq() {
return seq;
}
}
(3) main
import java.sql.SQLException;
import java.util.ArrayList;
public class SearchZipcodeEx03 {
public static void main(String[] args) {
try {
// 데이터베이스에 접근해서 값을 가져올 객체 생성
ZipcodeDAO dao = new ZipcodeDAO();
// 위 객체의 메서드로 결과값을 리턴받아 저장할 변수
ArrayList<ZipcodeTO> datas = dao.searchZipcode("신사");
for(ZipcodeTO to : datas) {
System.out.println(to.getZipcode());
System.out.println(to.getSido());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
실습2) 부서번호를 조회해서 사원 정보를 출력하는 프로그램
(1) DAO
데이터베이스에 접속하고 관련된 일을 직접 수행하는 실행객체로서
데이터베이스의 값들을 담을 EmpTO 객체를 생성하여 활용한다.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
public class EmpDAO {
private Connection conn = null;
// 생성자
// 데이터베이스 접속
public EmpDAO() throws ClassNotFoundException, SQLException{
String url = "jdbc:mysql://localhost:3307/sample";
String user = "root";
String password = "!123456";
Class.forName("org.mariadb.jdbc.Driver");
this.conn = DriverManager.getConnection(url, user, password);
// Connection conn = DriverManager.getConnection(url, user, password);
}
// SQL 구문별 메소드 - 동이름과 함께 호출되는 메서드는 그 결과값을 ArrayList<String>으로 리턴
public ArrayList<EmpTO> searchEmp(String strDeptno) throws ClassNotFoundException, SQLException{
ArrayList<EmpTO> datas = new ArrayList<EmpTO>();
String sql = "select empno, ename, mgr, hiredate, sal, comm, deptno from emp where deptno = ?";
// conn이 멤버변수로 선언되었기 때문에 this.를 붙여줘야함
PreparedStatement pstmt = this.conn.prepareStatement(sql);
pstmt.setString(1, strDeptno + "%");
ResultSet rs = pstmt.executeQuery();
while(rs.next()) {
String empno = rs.getString("empno");
String ename = rs.getString("ename");
String mgr = rs.getString("mgr");
String hiredate = rs.getString("hiredate");
String sal = rs.getString("sal");
String comm = rs.getString("comm");
String deptno = rs.getString("deptno");
EmpTO to = new EmpTO(empno, ename, mgr, hiredate, sal, comm, deptno);
datas.add(to);
}
return datas;
}
}
(2) DTO
데이터베이스에서 가져온 결과값들의 컬럼값들을 프로그램에서 사용할 수 있게 한행을 하나의 객체로 하여 속성값으로 컬럼값을 갖는 객체다. 이 객체를 통해 우린 프로그램에서 데이터베이스의 컬럼값들을 get / set 할 수 있다.
public class EmpTO {
private String empno;
private String ename;
private String mgr;
private String hiredate;
private String sal;
private String comm;
private String deptno;
public String getEmpno() {
return empno;
}
public EmpTO(String empno, String ename, String mgr, String hiredate, String sal, String comm, String deptno){
this.empno = empno;
this.ename = ename;
this.mgr = mgr;
this.hiredate = hiredate;
this.sal = sal;
this.comm = comm;
this.deptno = deptno;
}
public String getEname() {
return ename;
}
public String getMgr() {
return mgr;
}
public String getHiredate() {
return hiredate;
}
public String getSal() {
return sal;
}
public String getComm() {
return comm;
}
public String getDeptno() {
return deptno;
}
}
(3) main
import java.sql.SQLException;
import java.util.ArrayList;
public class SearchEmpEx01 {
public static void main(String[] args) {
try {
// 데이터베이스에 접근해서 값을 가져올 객체
EmpDAO dao = new EmpDAO();
// 위 객체의 메서드에서 결과를 리턴받아 저장할 변수
ArrayList<EmpTO> datas = dao.searchEmp("10");
for(EmpTO to : datas) {
System.out.print(to.getEmpno()+" ");
System.out.print(to.getEname()+" ");
System.out.print(to.getMgr()+" ");
System.out.print(to.getHiredate()+" ");
System.out.print(to.getComm()+" ");
System.out.print(to.getSal()+" ");
System.out.print(to.getDeptno());
System.out.println();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
네트워크
▷p1052
1. 웹 서버에 접속
=> 브라우저와 비슷한 역할
=> url 로 요청했을 자료에 접근하는 방법
* 크롤링(스크래핑)
openStream() -> IO
URLConnection
2. c(client)/s(server) 서버 프로그램 작성 방법
서버 - 클라이언트 (채팅)
IP
공인 아이피 - 인터넷 가능 - 라우터에서 나오는 ip
비공인 아이피 - 인터넷 불가능 (내부 아이피) - 라우터를 거쳐서 공유기를 통해서 나오는 ip
192.168.XXX.XXX 는 전부 비공인 아이피이다. 이런거 빼고 전부 공인이라고 보면된다.
내부에서만 접근 가능하다.
연결 : java.net.*
※ Point-to-Point 를 확대한게 블록체인
1. InetAddress
실습1) 어느 사이트의 ip주소를 알고 싶을 때 하는 방법
import java.net.InetAddress;
import java.net.UnknownHostException;
public class NetworkEx01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
// ip 정보
try {
InetAddress inetAddress1 = InetAddress.getByName("www.naver.com");
System.out.println(inetAddress1.getHostName());
System.out.println(inetAddress1.getHostAddress());
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
실행할 때마다 ip주소 다르게 출력됨
공격이 가능할 수도 있어서 ip주소 바뀌게 해놓음
1-1. 도메인 -> IP
DNS 서버를 상위기관에서 갖고 있다. IP를 치면 도메인, 도메인을 치면 IP가 나오게 되어 있다.
nslookkup 명령어 사용
C:\Users\김해선> nslookup
1-2. 도메인 -> ip
ip주소가 여러개인거는 어떻게 다 출력하냐? 반복문 사용
import java.net.InetAddress;
import java.net.UnknownHostException;
public class NetworkEx01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
// ip 정보(도메인)
try {
InetAddress inetAddress1 = InetAddress.getByName("www.naver.com");
System.out.println(inetAddress1.getHostName());
System.out.println(inetAddress1.getHostAddress());
InetAddress[] inetAddresses = InetAddress.getAllByName("www.naver.com");
for(InetAddress inetAddress : inetAddresses) {
System.out.println(inetAddress.getHostAddress());
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
2. URL
주소를 모두 알아서 분리해준다.
import java.net.MalformedURLException;
import java.net.URL;
public class NetworkEx02 {
public static void main(String[] args) {
// url 저장용 클래스
try {
URL url = new URL("https://search.naver.com/search.naver?sm=tab_hty.top&where=nexearch&query=%EB%82%B4+%EC%95%84%EC%9D%B4%ED%94%BC+%EC%A3%BC%EC%86%8C+%ED%99%95%EC%9D%B8&oquery=192.168.219.120&tqi=U8EphsprvxZssD82QtKssssstJh-459217");
System.out.println(url.getProtocol());
System.out.println(url.getHost());
System.out.println(url.getPort());
System.out.println(url.getPath());
System.out.println(url.getQuery());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
실습) html 문서 읽어오기 (html 출력)
(1) inputStream - 한글 깨져 나옴
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
public class NetworkEx03 {
public static void main(String[] args) {
InputStream is = null;
try {
// html 문서 읽어오기
URL url = new URL("https://m.naver.com"); // html
is = url.openStream();
int data = 0;
while((data = is.read())!= -1) {
System.out.print((char)data);
}
System.out.println();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(is != null)try { is.close();} catch(IOException e_) {}
}
}
}
(2) BufferedReader - 한글 안깨짐
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
public class NetworkEx04 {
public static void main(String[] args) {
BufferedReader br = null;
try {
// html 문서 읽어오기
URL url = new URL("https://m.naver.com"); // html
br = new BufferedReader(new InputStreamReader(url.openStream()));
String data = null;
while((data = br.readLine()) != null) {
System.out.println(data);
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(br != null)try { br.close();} catch(IOException e_) {}
}
}
}
2. URLConnection
URL보다 보강된 기능
연결에대한 정보를 알수 있다.
실습1) 연결에 대한 정보 확인 (위의 URL 실습과 연결됨)
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class NetworkEx05 {
public static void main(String[] args) {
try {
URL url = new URL("https://m.naver.com");
URLConnection conn = url.openConnection();
System.out.println(conn);
System.out.println(conn.getContent());
System.out.println(conn.getDate()); // timestamp
System.out.println(conn.getURL());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
이렇게 연결에 대한 정보를 알수있다는 걸 확인가능하다.
실습2) 문서 읽어오기
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class NetworkEx06 {
public static void main(String[] args) {
BufferedReader br = null;
try {
// URL url = new URL("https://m.naver.com");
// URLConnection conn = url.openConnection();
URLConnection conn = (new URL("https://m.naver.com")).openConnection();
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(br != null)try { br.close();} catch(IOException e_) {}
}
}
}
BufferedRedaer와 함께 문서 읽기 가능! ( URLConnection(URL + URLConnection), BufferedReader )
실습3) 이미지 파일 가져와서 저장하기
문서 뿐만아니라 다운로드도 받을 수 있다!
이미지 파일주소 긁어와서 저장할 수 있다.
파일을 주소를 받아와서 (BufferedInputStream) 내파일로 저장(BufferedOutputStream)해야한다.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class NetworkEx07 {
public static void main(String[] args) {
// https://t1.daumcdn.net/b2/creative/42429/ceb3377e6df4208fcd91164a0181d158.jpg
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
// 문자가 아니라서 BufferedInput(Output)Stream 쓴다.
String strURL = "https://t1.daumcdn.net/b2/creative/42429/ceb3377e6df4208fcd91164a0181d158.jpg";
try {
URLConnection conn = new URL(strURL).openConnection();
bis = new BufferedInputStream(conn.getInputStream());
bos = new BufferedOutputStream(new FileOutputStream("./image.jpg"));
int data = 0;
while((data = bis.read()) != -1) {
bos.write(data);
}
System.out.println("전송 완료");
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(bis != null)try {bis.close();} catch(IOException e) {}
if(bos != null)try {bos.close();} catch(IOException e) {}
}
}
}
문자가 아니라서 BufferedInput(Output)Stream썼다.
BufferedReader문자 파일일때만 쓰고 그 외는 전부 BufferedInput(Output)Stream 사용한다.
동영상 그런것도 가능하다.
3. 크롤링
페이지의 html 문자 읽어서 그부분만 추출하는 것을 크롤링이라고 한다.
날짜별 흐름같은걸 파악할 수도 있다. (어떤 토픽이 뉴스로 많이 올라왔는지 등등..)
실습1) www.daum.net 페이지 문서에 <ul class="list_txt"> ~ <\ul>내의 <li> 데이터들만 가져오기
(1) 내코드
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class NetworkEx08 {
public static void main(String[] args) {
BufferedReader br = null;
String strURL = "https://www.daum.net";
try {
URLConnection conn = new URL(strURL).openConnection();
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
boolean li = false;
String line = "";
while((line = br.readLine()) != null) {
if(line.startsWith("</ul>")) {
li = false;
}
if(li) {
System.out.println(line);
}
if(line.startsWith("<ul class=\"list_txt\">")) {
li = true;
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(br != null)try {br.close();} catch(IOException e) {}
}
}
}
(2) 강사님 코드
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class NetworkEx08 {
public static void main(String[] args) {
BufferedReader br = null;
String strURL = "https://www.daum.net";
try {
URLConnection conn = new URL(strURL).openConnection();
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
boolean li = false;
String line = "";
while((line = br.readLine()) != null) {
if(line.startsWith("<ul class=\"list_txt\">")) {
while(true) {
String htmlLine = br.readLine();
if(htmlLine.equals("</ul>")) {
System.out.println(htmlLine);
}else {
break;
}
}
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(br != null)try {br.close();} catch(IOException e) {}
}
}
}
실습2) www.daum.net 페이지 문서에 <a>태그 안의 텍스트부분만 가져오기
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class NetworkEx08 {
public static void main(String[] args) {
BufferedReader br = null;
String strURL = "https://www.daum.net";
try {
URLConnection conn = new URL(strURL).openConnection();
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
while((line = br.readLine()) != null) {
if(line.startsWith("<ul class=\"list_txt\">")) {
while(true) {
String htmlLine = br.readLine();
if(!htmlLine.equals("</ul>")) {
// <a 찾기
if(htmlLine.startsWith("<a")) {
// >"방역 실패가 왜 우리 책임이야" 민주노총, 여의도 집회 강행..1명 체포<
System.out.println(htmlLine.substring(
htmlLine.indexOf(">")+1, htmlLine.lastIndexOf("<")));
}
}else {
break;
}
}
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if(br != null)try {br.close();} catch(IOException e) {}
}
}
}
이렇게 URLConnection에 InputStream을 사용해서 크롤링을 해올수 있다.
4. TCP 네트워킹
▷p105
네트워킹
TCP - 전화(O) - 신뢰성
UDP - 방송(X) - 신속성
ServerSocket - port 1. (cmd)
Socket - ip / port -> protocol 2. (eclipse)
자바는 TCP 네트워킹을 위해 java.net.ServerSocket 과 java.net.Socket 클래스를 제공하고 있다.
ServerSocket 과 Socket의 용도
- ServerSocket : 클라이언트의 연결 요청을 기다리면서 연결 수락을 담당하는 것
- Socket : 연결된 클라이언트와 통신을 담당하는 것
지금부터 서버와 클라이언트를 만들어서 직접 구현해 볼것이다. 가장 먼저 서버를 먼저만드는데 ServerSocket을 중심으로 만든다.
흐름은 다음과 같다.
- 서버 실행 → 서버 대기상태 → 클라이언트 실행 → 서버마저 실행 → 끝
- 서버 실행X → 서버 대기 X → 클라이언트 실행 → 클라이언트 서버랑 연결 실패
(1) Server
포트 7777번으로 열어두고 서버를 준비시킨다. accept()로 serverSocket이 Socket에 데이터를 보내기
package pack1;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerEx01 {
public static void main(String[] args) {
System.out.println("시작");
ServerSocket serverSocket = null;
Socket socket = null;
try {
serverSocket = new ServerSocket( 7777 );
System.out.println("서버가 준비되었습니다.");
// accept()로 대기하고 있다가
// client를 실행시키면 클라이언트 준비되었다고 띄우고 종료됨
socket = serverSocket.accept();
System.out.println("클라이언트가 준비되었습니다");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("[에러]" + e.getMessage());
} finally {
if(socket != null) try {socket.close();}catch(IOException e) {}
if(serverSocket != null) try {serverSocket .close();}catch(IOException e) {}
}
System.out.println("끝");
}
}
cmd에서 실행
C:\Java\java\eclipse-workspace\SocketEx01\bin>java pack1.TCPServerEx01
(2) Client
package pack1;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClientEx01 {
public static void main(String[] args) {
System.out.println("시작");
Socket socket = null;
try {
System.out.println("서버와 연결 중");
socket = new Socket("localhost", 7777);
System.out.println("연결 완료");
} catch (UnknownHostException e) {
System.out.println("[에러]" + e.getMessage());
} catch (IOException e) {
System.out.println("[에러]" + e.getMessage());
} finally {
if(socket != null) try { socket.close();} catch(IOException e){}
}
System.out.println("끝");
}
}
(3) 실행 결과
실습1) 서버에서 클라이언트로 데이터보내기
서버가 socket에 write하고 클라이언트가 socket을 read한다고 생각하면된다.
(1) Server
package pack2;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerEx01 {
public static void main(String[] args) {
System.out.println("시작");
ServerSocket serverSocket = null;
Socket socket = null;
BufferedWriter bw = null;
try {
serverSocket = new ServerSocket( 7777 );
System.out.println("서버가 준비되었습니다.");
socket = serverSocket.accept();
System.out.println("클라이언트가 준비되었습니다");
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
// \n은 끝이라는 의미
bw.write("Hello socket\" + \"\\n");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("[에러]" + e.getMessage());
} finally {
if(bw != null) try {bw.close();}catch(IOException e) {}
if(socket != null) try {socket.close();}catch(IOException e) {}
if(serverSocket != null) try {serverSocket .close();}catch(IOException e) {}
}
System.out.println("끝");
}
}
(2) Client
package pack2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClientEx01 {
public static void main(String[] args) {
System.out.println("시작");
Socket socket = null;
BufferedReader br = null;
try {
System.out.println("서버와 연결 중");
socket = new Socket("localhost", 7777);
System.out.println("연결 완료");
br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("MSG : " + br.readLine());
} catch (UnknownHostException e) {
System.out.println("[에러]" + e.getMessage());
} catch (IOException e) {
System.out.println("[에러]" + e.getMessage());
} finally {
if(br != null) try { br.close();} catch(IOException e){}
if(socket != null) try { socket.close();} catch(IOException e){}
}
System.out.println("끝");
}
}
(3) 실행 결과
서버에서 클라이언트로 데이터를 보내려면
서버에선 OutputStream
클라이언트에선 InputStream 으로 만들어줘야한다.
"을 출력하려면 앞에 \를 붙여주면 된다.
실습2) 클라이언트로부터 서버가 데이터를 받아서 그걸 다시 클라이언트로 보내기 ( 에코 )
※ 중요 포인트
stream이 끝나면 끝났다는걸 알려줘야한다. -> flush()
write()다음에 꼭 해줘야하는게 flush()이다.
안해주면 서버 진행이 안된다.
한국어는 깨져서 나오므로 utf-8 로 보내고 받을거라는 선언을 해줘야한다.
읽을때 readLine()을 한다는걸 고려해서 write()에서 마지막에 "\n"을 붙여줘야한다.
(1) Server
package pack3;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerEx01 {
public static void main(String[] args) {
System.out.println("시작");
ServerSocket serverSocket = null;
Socket socket = null;
BufferedReader br = null;
BufferedWriter bw = null;
try {
serverSocket = new ServerSocket( 7777 );
System.out.println("서버가 준비되었습니다.");
socket = serverSocket.accept();
System.out.println("클라이언트가 준비되었습니다");
br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8"));
bw.flush();
String msg = br.readLine();
System.out.println("client msg: " + msg);
bw.write(msg + "\n");
System.out.println("전송 완료");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("[에러]" + e.getMessage());
} finally {
// 소켓을 닫기 전에 닫아줘야함
if(bw != null) try {bw.close();}catch(IOException e) {}
if(br != null) try {br.close();}catch(IOException e) {}
if(socket != null) try {socket.close();}catch(IOException e) {}
if(serverSocket != null) try {serverSocket .close();}catch(IOException e) {}
}
System.out.println("끝");
}
}
(2) Client
package pack3;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClientEx01 {
public static void main(String[] args) {
System.out.println("시작");
Socket socket = null;
BufferedWriter bw = null;
BufferedReader br = null;
try {
System.out.println("서버와 연결 중");
socket = new Socket("localhost", 7777);
System.out.println("연결 완료");
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8"));
br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
bw.write("Hello Server 김해선"+ "\n");
System.out.println("전송 완료");
bw.flush();
String msg = br.readLine();
System.out.println("MSG : " + msg);
} catch (UnknownHostException e) {
System.out.println("[에러]" + e.getMessage());
} catch (IOException e) {
System.out.println("[에러]" + e.getMessage());
} finally {
if(br != null) try { br.close();} catch(IOException e){}
if(bw != null) try { bw.close();} catch(IOException e){}
if(socket != null) try { socket.close();} catch(IOException e){}
}
System.out.println("끝");
}
}
(3) 실행 결과
응용문제) 클라이언트로부터 구구단 단수를 받아서 서버가 구구단 식을 만들어 보내고 클라이언트가 출력하기
*** 내 코드
(1) Server
package gugudan;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerEx01 {
public static void main(String[] args) {
System.out.println("시작");
ServerSocket serverSocket = null;
Socket socket = null;
BufferedReader br = null;
BufferedWriter bw = null;
try {
serverSocket = new ServerSocket( 7777 );
System.out.println("서버가 준비되었습니다.");
socket = serverSocket.accept();
System.out.println("클라이언트가 준비되었습니다");
br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8"));
bw.flush();
String dan = br.readLine();
int intdan = Integer.parseInt(dan);
for(int i = 1; i<=9; i++) {
bw.write(intdan + "X" + i + "=" + intdan*i + "\n");
}
System.out.println("전송 완료");
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println("[에러]" + e.getMessage());
} finally {
// 소켓을 닫기 전에 닫아줘야함
if(bw != null) try {bw.close();}catch(IOException e) {}
if(br != null) try {br.close();}catch(IOException e) {}
if(socket != null) try {socket.close();}catch(IOException e) {}
if(serverSocket != null) try {serverSocket .close();}catch(IOException e) {}
}
System.out.println("끝");
}
}
(2) Client
package gugudan;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class TCPClientEx01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("시작");
Socket socket = null;
BufferedWriter bw = null;
BufferedReader br = null;
int dan = 0;
try {
System.out.println("서버와 연결 중");
socket = new Socket("localhost", 7777);
System.out.println("연결 완료");
dan = sc.nextInt();
System.out.println(dan + "단");
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "utf-8"));
br = new BufferedReader(new InputStreamReader(socket.getInputStream(), "utf-8"));
bw.write(dan + "\n");
System.out.println("전송 완료");
bw.flush();
String dans = "";
while((dans = br.readLine()) != null) {
System.out.println(dans);
}
} catch (UnknownHostException e) {
System.out.println("[에러]" + e.getMessage());
} catch (IOException e) {
System.out.println("[에러]" + e.getMessage());
} finally {
if(br != null) try { br.close();} catch(IOException e){}
if(bw != null) try { bw.close();} catch(IOException e){}
if(socket != null) try { socket.close();} catch(IOException e){}
if(sc != null) try { sc.close();} catch(Exception e){}
}
System.out.println("끝");
}
}
(3) 실행 결과