목적 코드가 어떤 것인가? → getRequest() 같은 경우 목적은 return queue.remove(); 이다
가도 조건이 어떤 것인가? → synchronized while(가드조건) { wait(); } 목적코드;
guarded suspension 패턴
guaded Object(LinkedList<Request>();
)의 상태변화를 해야하는 코드가 반드시 존재해야한다.(stateChanging Method)
※위에 내용 정리※
guarded object : queue → private final Queue<Request> queue = new LinkedList<Request>();
guarded method : getRequest()
2.1 목적코드 : queue.remove();
2.2 가드조건 : queue.peek() == null → wait()
2.3 synchronized method() { while(가드조건) { wait() } 목적코드; }
stateChanging method : putRequest() → guarded object의 상태 변화
3.1 synchronized method() { guarded object의 상태 변화코드; notifyAll(); }
LinkedBlockingQueue<>()
take(), put() → 동기화 시켜주고 wait() 까지 지원해준다. 꺼낼게 없으면 못꺼내고 꺼낼게 들어오면 꺼내는 걸 구현할때 사용한다.
통신이 가능한 디바이스(인터넷)
주소창에 도메인 이름(naver.com)을 넣으면 DNS(Domain name server)로 이동한다. DNS 안 목록에 있는 도메인 이름의 IP 주소를 돌려주고 Server는 돌려받은 IP주소로 다시 요청한다.
public class NSLookUp {
public static void main(String[] args) {
String domain = JOptionPane.showInputDialog(
"도메인을 입력하시오"
);
// IP 나타내는 객체
InetAddress inetaddr[] = null;
try {
inetaddr = InetAddress.getAllByName(domain);
} catch(UnknownHostException e) {
e.printStackTrace();
}
for(int i = 0; i < inetaddr.length; i++) {
System.out.println(inetaddr[i].getHostName());
System.out.println(inetaddr[i].getHostAddress());
System.out.println(inetaddr[i].toString());
System.out.println("---------------------------");
}
}// main
}
inetaddr = InetAddress.getAllByName(domain);
→getHostName()
: 도메인 이름getHostAddress()
: 아이피 번호toString()
: 호스트 네임 / 호스트 어드레스public class EchoServer {
public static void main(String[] args) {
Socket sock = null;
OutputStream out = null;
OutputStreamWriter osw = null;
PrintWriter pw = null;
InputStream in = null;
InputStreamReader isr = null;
BufferedReader br = null;
try {
ServerSocket server = new ServerSocket(10001);
System.out.println("접속을 기다립니다.");
sock = server.accept();
InetAddress inetaddr = sock.getInetAddress();
System.out.println(
inetaddr.getHostAddress() + " 로 부터 접속하였습니다."
);
out = sock.getOutputStream();
in = sock.getInputStream();
osw = new OutputStreamWriter(out);
pw = new PrintWriter(osw);
isr = new InputStreamReader(in);
br = new BufferedReader(isr);
String line = null;
while( (line = br.readLine()) != null ) {
System.out.println(
"클라이언트로 부터 전송받은 문자열 : " + line
);
pw.println(line);
pw.flush();
}
System.out.println(line);
} catch(Exception e) {
System.out.println(e);
} finally {
try {
br.close();
} catch(Exception e) {}
try {
isr.close();
} catch(Exception e) {}
try {
in.close();
} catch(Exception e) {}
try {
pw.close();
} catch(Exception e) {}
try {
osw.close();
} catch(Exception e) {}
try {
out.close();
} catch(Exception e) {}
try {
sock.close();
} catch(Exception e) {}
}
} // main
}
public class EchoClient {
public static void main(String[] args) {
Socket sock = null;
OutputStream out = null;
OutputStreamWriter osw = null;
PrintWriter pw = null;
InputStream in = null;
InputStreamReader isr = null;
BufferedReader br = null;
BufferedReader keyboard = null;
InputStreamReader keyIsr = null;
try {
sock = new Socket("127.0.0.1", 10001);
keyIsr = new InputStreamReader(System.in);
keyboard = new BufferedReader(keyIsr);
out = sock.getOutputStream();
in = sock.getInputStream();
osw = new OutputStreamWriter(out);
pw = new PrintWriter(osw);
isr = new InputStreamReader(in);
br = new BufferedReader(isr);
String line = null;
while( (line = keyboard.readLine()) != null ) {
if(line.equals("quit")) break;
pw.println(line);
pw.flush();
String echo = br.readLine();
System.out.println("서버로부터 전달받은 문자열 : " + echo);
}
pw.close();
br.close();
sock.close();
} catch(Exception e) {
System.out.println(e);
} finally {
try {
keyboard.close();
} catch (Exception e) {}
try {
keyIsr.close();
} catch (Exception e) {}
try {
br.close();
} catch (Exception e) {}
try {
isr.close();
} catch (Exception e) {}
try {
in.close();
} catch (Exception e) {}
try {
pw.close();
} catch (Exception e) {}
try {
osw.close();
} catch (Exception e) {}
try {
out.close();
} catch (Exception e) {}
try {
sock.close();
} catch (Exception e) {}
}
} // main
}
서버 먼저 실행하고 클라이언트 실행하기
실행 결과
ServerSocket
: 포트 번호로 접속 가능하다. 생성자에 10001은 포트 번호
server.accept()
: 서버 소켓에 accept되면서 클라이언트가 접속할때까지 블로킹 상태가 된다.(Not Runnable 상태)
new Socket("127.0.0.1", 10001);
: new Socket(ip, port);
getInetAddress()
뽑아냈다는건 클라이언트에 IP 주소를 가져온다.while( (line = br.readLine()) != null )
읽을게 있을때까지 readLine()
에서 블로킹 된다.readLine()
에서 멈춰있다. 키보드로 입력하면 서버의 readline으로 line이 출력이 되고 클라이언트에 readline으로 넘어가고 콘솔창에 출력되고 난 다음 키보드로에서 대기한다.InputStreamReader(System.in);
BufferedReader(keyIsr);
readLine() 발생String echo = br.readLine();
에서 대기한다.br.readLine();
에서 대기한다.