ifconfig -a
new Socket("localhost", 8888);
new Socket("127.0.0.1", 8888);
new Socket("접속하려는 상대편의 네트워크 주소, IP Address", 포트번호(port number));
// 네트워크 준비
try {
Socket socket = new Socket("127.0.0.1", 8888 );
// 같은 컴퓨터 내에 서버와 클라이언트가 존재하므로 정확한 IP address 대신, 127.0.0.1(local host)이 가능하다.
// (접속할 IP address, port num)
} catch (Exception e) {
e.printStackTrace();
}
IP Address: 네트워크 상에서의 컴퓨터 식별 번호
= Ram 카드에 부여된 번호= 지구에서 유일한 값 = 국제 기구에서 번호 관리
Port 번호: Application 식별 번호
package com.bitcamp.board;
import java.net.Socket;
public class ClientApp {
public static void main(String[] args) {
System.out.println("[게시글 관리 클라이언트]");
// 네트워크 준비
//=> 정상적으로 연결되었으면, Socket 객체를 리턴한다.
try {
Socket socket = new Socket("127.0.0.1", 8888 );
System.out.println("연결되었음!");
// 네트워크 끊기
// => 서버와 연결된 것을 끊는다.
socket.close();
System.out.println("연결을 끊었음!");
} catch (Exception e) {
e.printStackTrace();
}//try-catch()
System.out.println("종료");
}//main()
}
package com.bitcamp.board;
import java.net.ServerSocket;
import java.net.Socket;
public class ServerApp {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("[게시글 데이터 관리 서버]");
try {
// 네트워크 준비
// => 클라이언트 연결을 관리할 객체를 준비한다.
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("서버 소켓 준비 완료!");
// 클라이언트의 연결을 기다림
// => 클라이언트와 연결되면 그 클라이언트와 통신할 준비를 한다.
// 즉, Socket 객체 리턴
Socket socket = serverSocket.accept();
System.out.println(" 클라이언트와 연결 되었음!");
// 클라이언트와 연결된 것을 끊는다.
// => 클라이언트와 연결될 때까지 리턴하지 않는다.
socket.close();
System.out.println("클라이언트와 연결 되었음!");
// 네트워크 종료
// => 더 이상 클라이언트와 연결하고 싶지 않다면 네트워크를 종료한다.
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}//try-catch()
System.out.println("서버 종료!");
}//main()
}
Decorator: I/O 객체에 덧붙여서 기능을 확장시킨다.
package com.bitcamp.board;
import java.net.Socket;
public class HTTPClient {
public static void main(String[] args) throws Exception {
try(
Socket socket = new Socket("www.auction.co.kr", 80); // web server port number: 80
BufferedReader in = new BufferedReader( new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());){
// HTTP 프로토콜에 따라서 메인 웹 페이지를 요청한다.
out.println("GET / HTTP/1.1"); // root 에 있는 메인 페이지를원한다.
out.println("Host: www.auction.co.kr");
out.println(); // 요청에 대한 정보 끝
// 웹서버의 응답을 출력한다.
String line;
while((line = in.readLine()) != null) {
System.out.println(line);
}
}
}
}
안녕하세요!
만 출력한다.package com.bitcamp.study;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class HTTPServer {
public static void main(String[] args) throws Exception{
try(ServerSocket ss = new ServerSocket(80);){ // http://127.0.0.1/ 이 다음은 내가 원하는 옵션인데 이 서버단에서 설정을 안해줘서 그냥 계속 안녕하세요!만 출력한다.
System.out.println("서버 시작!!!!!!");
while(true) {
try(
Socket socket = ss.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintStream out = new PrintStream(socket.getOutputStream());
){//try()
System.out.println("클라이언트가 연결됨!!!!!!!");
// 클라이언트가 보낸 데이터를 읽는다.
System.out.println("----------------------------");
String line;
while((line = in.readLine())!=null) {
if(line.length() == 0) { // 클라이언트가 빈 줄을 보내면, 읽기를 끝낸다.
break;
}
System.out.println(line);
}
// 클라이언트에게 응답한다.
out.println("HTTP/1.1 200 OK");
out.println("Content-Type: text/html;charset=UTF-8"); // content의 정보
out.println(); // 이제부터 본격적으로 콘텐트를 보내겠다고 알린다.
out.println("<html>");
out.println("<head>");
out.println("<title>Hello!</title>");
out.println("</head>");
out.println("<body>");
out.println("<h1>안녕하세요!</h1>");
out.println("</body>");
out.println("</html>");
}// try()
}// while
}// try()
}//main()
}//class
/*
* 게시글 메뉴 처리 클래스
*/
package com.bitcamp.board.handler;
public class BoardHandler extends AbstractHandler {
// 게시글 목록을 관리할 객체 준비
private BoardDao boardDao;
String dataName;
DataInputStream in;
DataOutputStream out;
public BoardHandler(String dataName, DataInputStream in, DataOutputStream out){
// 수퍼 클래스의 생성자를 호출할 때 메뉴 목록을 전달한다.
super(new String[] {"목록", "상세보기", "등록", "삭제", "변경"});
this.dataName = dataName;
this.in = in;
this.out =out;
boardDao = new BoardDao(dataName);
// 이제 로드는 서버애서!
}
@Override
public void service(int menuNo) {
try {
switch (menuNo) {
case 1: this.onList(); break;
case 2: this.onDetail(); break;
case 3: this.onInput(); break;
case 4: this.onDelete(); break;
case 5: this.onUpdate(); break;
}
}catch(Exception e) {
throw new RuntimeException(e); //
}
}
private void onList() {
try {
out.writeUTF(dataName);
out.writeUTF("findAll");
System.out.println(in.readUTF());
}catch(Exception e) {
throw new RuntimeException(e);
}
}
private void onDetail() {
try {
out.writeUTF(dataName);
out.writeUTF("findByNumber");
System.out.println(in.readUTF());
}catch(Exception e) {
throw new RuntimeException(e);
}
}
private void onInput() throws Exception{
try {
out.writeUTF(dataName);
out.writeUTF("insert");
System.out.println(in.readUTF());
}catch(Exception e) {
throw new RuntimeException(e);
}
}
private void onDelete() throws Exception{
try {
out.writeUTF(dataName);
out.writeUTF("delete");
System.out.println(in.readUTF());
}catch(Exception e) {
throw new RuntimeException(e);
}
}
private void onUpdate() throws Exception{
try {
out.writeUTF(dataName);
out.writeUTF("update");
System.out.println(in.readUTF());
}catch(Exception e) {
throw new RuntimeException(e);
}
}
}
public class ClientApp {
//breadcrumb 메뉴를 저장할 스택을 준비
public static Stack<String> breadcrumbMenu = new Stack<>();
public static void main(String[] args) {
System.out.println("[게시글 관리 클라이언트]");
// 네트워크 준비
//=> 정상적으로 연결되었으면, Socket 객체를 리턴한다.
try (Socket socket = new Socket("127.0.0.1", 8888 );
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());){
System.out.println("연결되었음!");
welcome();
// 핸들러를 담을 레퍼런스 배열을 준비한다.
Handler[] handlers = new Handler[] { // 파일명을 목적에 맞게 각각 전달
new BoardHandler("board", in, out), // 게시판
new BoardHandler("reading", in, out), // 독서록
new BoardHandler("visit", in, out), // 방명록
new BoardHandler("notice", in, out), // 공지사항
new BoardHandler("daily", in, out), // 일기장
//new MemberHandler("member", in, out) // 회원
};
// "메인" 메뉴의 이름을 스택에 등록한다.
breadcrumbMenu.push("메인");
// 메뉴명을 저장할 배열을 준비한다.
String[] menus = {"게시판", "독서록", "방명록", "공지사항", "일기장", "회원"};
loop:
while (true) {
// 메인 메뉴 출력
printTitle();
printMenus(menus);
System.out.println();
try {
int mainMenuNo = Prompt.inputInt("메뉴를 선택하세요[1..6](0: 종료) ");
if (mainMenuNo < 0 || mainMenuNo > menus.length) {
System.out.println("메뉴 번호가 옳지 않습니다!");
continue; // while 문의 조건 검사로 보낸다.
} else if (mainMenuNo == 0) {
out.writeUTF("exit"); // client가 서버와의 연결에서 나가겠다고 하는 순간. // out은 서버로 보내는 것이다.
break loop;
}
// 메뉴에 진입할 때 breadcrumb 메뉴바에 그 메뉴를 등록한다.
breadcrumbMenu.push(menus[mainMenuNo - 1]);
// 메뉴 번호로 Handler 레퍼런스에 들어있는 객체를 찾아 실행한다.
handlers[mainMenuNo - 1].execute();
breadcrumbMenu.pop();
} catch (Exception ex) {
System.out.println("입력 값이 옳지 않습니다.");
}
} // while
Prompt.close();
// 네트워크 끊기
// => 서버와 연결된 것을 끊는다.
//socket.close();
System.out.println("연결을 끊었음!");
} catch (Exception e) {
e.printStackTrace();
}//try-catch()
System.out.println("종료!\n");
}//main()
static void welcome() {
System.out.println("[게시판 애플리케이션]");
System.out.println();
System.out.println("환영합니다!");
System.out.println();
}
static void printMenus(String[] menus) {
for (int i = 0; i < menus.length; i++) {
System.out.printf(" %d: %s\n", i + 1, menus[i]);
}
}
protected static void printTitle() {
StringBuilder builder = new StringBuilder();
for(String title: breadcrumbMenu) {
if(!builder.isEmpty()) {
builder.append(" > ");
}
builder.append(title);
}
System.out.printf("%s:\n", builder.toString());
}
}
/*
* board 데이터 처리
*/
package com.bitcamp.board.servlet;
public class BoardServlet implements Servlet{
// 게시글 목록을 관리할 객체 준비
private BoardDao boardDao;
public BoardServlet(String dataName){
}
@Override
public void service(DataInputStream in, DataOutputStream out) {
try {
String command = in.readUTF();
switch (command) {
case "findAll":
out.writeUTF("success");
break;
case "findByNumber":
out.writeUTF("success");
break;
case "insert":
out.writeUTF("success");
break;
case "update":
out.writeUTF("success");
break;
case "delete":
out.writeUTF("success");
break;
default:
out.writeUTF("fail");
}
}catch(Exception e) {
throw new RuntimeException(e); //
}
}
}
package com.bitcamp.board;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import com.bitcamp.board.servlet.BoardServlet;
public class ServerApp {
public static void main(String[] args) {
System.out.println("[게시글 데이터 관리 서버]");
try (
// 네트워크 준비(TCP 방식)
// => 클라이언트 연결을 관리할 객체를 준비한다.
ServerSocket serverSocket = new ServerSocket(8888);)
{
System.out.println("서버 소켓 준비 완료!");
try(
// 클라이언트의 연결을 기다림
// => 클라이언트와 연결되면 그 클라이언트와 통신할 준비를 한다.
// 즉, Socket 객체 리턴 (연결 -> socket 객체 받기)
Socket socket = serverSocket.accept(); //처음에 여기서 소켓 받을 때까지 기다린다.
// 클라이언트와 데이터를 주고 받는다.
// 클라이언트가 보낸 데이터를 읽을 때 사용할 도구를 준비한다.
//InputStream in = socket.getInputStream(); → 곧바로 ()안에 넣어 준다.
// 클라이언트와 데이터를 주고 받고 싶은데, socket이 주는 데이터는 byte로만 전달한다. => 부품, dataInputStream을 장착한다.
// => 즉, 데이터를 읽을 때 primitive type 또는 String 타입의 값을 보다 손쉽게 읽을 수 있도록 기존의 입력 도구에 보조 도구(decorator)를 붙여서 사용한다.
DataInputStream in = new DataInputStream( socket.getInputStream());
// => 클라이언트로 데이터를 보낼 때 사용할 도구를 준비한다.
//OutputStream out = socket.getOutputStream();
// => 즉, 데이터를 출력할 때 primitive type 또는 String 타입의 값을 보다 손쉽게 출력할 수 있도록 기존의 입력 도구에 보조 도구(decorator)를 붙여서 사용한다.
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
)//try()
{
System.out.println(" 클라이언트와 연결 되었음!");
// 클라이언트 요청을 처리할 객체 준비
BoardServlet boardServlet = new BoardServlet("board");
BoardServlet readingServlet = new BoardServlet("reading");
BoardServlet visitServlet = new BoardServlet("visit");
BoardServlet noticeServlet = new BoardServlet("notice");
BoardServlet dailyServlet = new BoardServlet("daily");
while(true) {
// 클라이언트와 서버 사이에 정해진 규칙(protocol)에 따라 데이터를 주고 받는다.
//
// 데이터 명 읽기
// 클라이언트가 문자열 보낼때 까지 기다린다.
// read는 내가 원하는 값이 들어올 때까지 기다린다. 내가 원할 때 읽는 것 X.
String dataName = in.readUTF();
if(dataName.equals("exit")) { // client에서 exit할때까지 반복
break;
}
switch(dataName) {
case "board": boardServlet.service(in, out); break;
case "reading": readingServlet.service(in, out); break;
case "visit": visitServlet.service(in, out); break;
case "notice": noticeServlet.service(in, out); break;
case "daily": dailyServlet.service(in, out); break;
default:
out.writeUTF("fail");
}
}
// 클라이언트와 연결된 것을 끊는다.
// => 클라이언트와 연결될 때까지 리턴하지 않는다.
System.out.println("클라이언트와 연결을 끊었음!");
// 네트워크 종료
}// 안쪽 try
}catch (Exception e) {
e.printStackTrace();
}// 바깥쪽 try-catch()
System.out.println("서버 종료!");
}//main()
}