서버-클라이언트의 기초

이동언·2024년 7월 21일

new world

목록 보기
10/62
post-thumbnail

7.18(목)

1. 파일을 전달하는 속도가 빠르려면?

📌 I/O의 횟수가 적을수록
📌 I/O의 데이터 양이 적을수록

1-1. Buffer

👉 입출력의 속도 개선을 위해 버퍼를 사용한다.

  • buffer를 이용한 속도차이 비교해보기
public class TimeCheck {
    public static void main(String[] args) throws Exception{

        FileInputStream fis = new FileInputStream("aaa.jpeg"); //기존에 가지고있는 사진
        FileOutputStream fos = new FileOutputStream("copy.jpeg"); //aaa사진을 복사하여 copy사진을 만든다

        byte [] buffer = new byte[1024*8]; //8kb만큼 읽고 쓰기

        long start = System.currentTimeMillis(); //복사 시작시간

        while(true){ //buffer배열에 있는 byte값을 순차적으로

            int count = fis.read(buffer); //count라는 정수에 buffer의 순차값을 읽고
            if(count == -1){
                break;
            }
            fos.write(buffer, 0, count); // 순차값을 작성한다.
        }
        long end = System.currentTimeMillis(); //복사 종료시간

        System.out.println("time : " + (end - start)); //복사 걸린시간

    }
}

1-2. 요청헤더 / 응답헤더

  • Request headers
    👉 클라이언트가 서버로 원하는 조건에 대한 정보를 서버에게 전달.
    👉 ex) 서버의 호스트 이름 또는 IP주소, 클라이언트가 처리할 수 있는 미디어타입

  • Response headers
    👉 서버가 클라이언트에게 응답을 돌려줄 때의 데이터 정보와 상태를 전달



2-1. 서버에 접속한 클라이언트의 정보 얻기

public class Server1 {
    public static void main(String[] args) throws Exception {

        //서버소켓만들기
        ServerSocket serverSocket = new ServerSocket(5555);
        System.out.println("Ready--------------");

        //한번에 많이 퍼 담을 바구니 만들기
        //byte 배열안에 값이 적을수록 적은 양의 데이터를 옮겨 담으니 자주왔다갔다 해야해서
        //받고 읽는 시간이 더 늘어남
        byte [] buffer = new byte[1024];

        while (true){
            //클라이언트 올때까지 대기, 연결수락
            Socket socket = serverSocket.accept();

            //소켓에 빨때 꼽아서 읽기
            InputStream inputStream = socket.getInputStream();
            int len = inputStream.read(buffer);
            // 해당 버퍼를 int값으로 읽기(퍼담기)

            System.out.println(new String(buffer,0,len));
            //버퍼의 0 부터 최대버퍼까지 새로운 문자열로 읽기
        }

👆 코드를 분석해보자

  1. 서버소켓을 만들어놓기
  2. buffer의 배열크기 만큼 한번에 데이터를 옮겨담기 때문에 퍼 담을 바구니라고 명시
  3. Soker.accept를 통해서 클라이언트가 들어오길 기다린다.
  4. inputStream통해서 소켓에 빨대 꼽기
  5. int Len에 퍼 담은 데이터를 정수로 변경
  6. 새로운 문자열로 데이터를 변경하여 정보를 출력되도록 만든다.

2-2. Server-Side-Rendering

public class Server2 { 
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(5555); //서버소켓 생성
        out.println("ready ----------------------");

        byte [] buffer = new byte[1024]; //바구니 생성

        while (true) {

            try( Socket socket = serverSocket.accept(); //소켓연결 생성
                 OutputStream out = socket.getOutputStream(); //소켓에서 빠져나가는 빨대 연결
                  ){
                String msg = "<h1>Hello World "+currentTimeMillis()+"</h1>"; //이렇게 출력할예정
                out.write(new String("HTTP/1.1 200 OK\r\n").getBytes());
                out.write(new String("Cache-Control: private\r\n").getBytes());
                out.write(new String("Content-Type: text/html; charset=UTF-8\r\n\r\n").getBytes());

                out.write(msg.getBytes(StandardCharsets.UTF_8));

            }

👆 코드를 분석해보자

  1. 서버생성해서 웹 페이지에 원하는 결과 출력하기
  2. try-with-resources를 사용하여 자동으로 close되도록 만들기

2-3. 이미지 보여주기

public class Image {
    public static void main(String[] args) throws Exception {

        ServerSocket serverSocket = new ServerSocket(5555);
        System.out.println("ready ------");

    while(true){
        try(Socket socket = serverSocket.accept(); //연결소켓
            OutputStream out = socket.getOutputStream();
            //out을 통해 읽은 파일을 정해진 이름으로 복제가 아닌 웹에 뛰워놓기용
            FileInputStream fin = new FileInputStream("aaa.jpeg") //aaa라는 파일을 읽기
            ) {

                out.write(new String("HTTP/1.1 200 OK\r\n").getBytes()); //상태코드
                out.write(new String("Cache-Control: private\r\n").getBytes());
                out.write(new String("Content-Type: image/jpeg; charset=UTF-8\r\n\r\n").getBytes());
                // image를 보내겠다는 코드

            byte [] buffer = new byte[1024];//바구니

            while (true) {

                int count = fin.read(buffer);
                if (count == -1) break;
                    out.write(buffer,0,count);

👆 코드를 분석해보자

  1. 파일을 읽을때는 FileInput을 썻는데 왜 파일을 웹에 올릴때는 FileOutput을 안썼을까?
    👉 bbb.jpg라는 파일로 복제를 하기 위해선 Fileoutput을 써야하지만 단순히 웹에 올리기 위해서 이므로 outputStream을 사용함.

2-4. Client / Server 둘 다 해보기.

  • Server
public class Server {
    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(5555); //소켓 생성
        System.out.println("ready ---------");

        try(Socket socket = serverSocket.accept(); //연결소켓생성
            FileInputStream fis = new FileInputStream("bbb.jpg"); //복제할 파일
            OutputStream os = socket.getOutputStream();){ //소켓에 연결하여 파일전달 빨대
            byte[] buffer = new byte[1024];
            while(true) {

                int count = fis.read(buffer);
                if(count == -1) {break;}
                os.write(buffer, 0, count);
            }//end while

👆 코드를 분석해보자

  1. 서버의 파일을 서버에 접속된 클라이언트에게 복제해주는것.
  2. 소켓을 생성해서 복제할 파일을 FileInput으로 받고, OutputStream을 통해 소켓으로 전달.

  • Client
public class Client {
    public static void main(String[] args) throws Exception {

        Socket socket = new Socket("127.0.0.1", 5555); //소켓생성하여 상대방과 연결

        InputStream is = socket.getInputStream(); //소켓에 연결하여 파일빨아들이는 빨대
        FileOutputStream fos = new FileOutputStream("copyb.jpg"); //소켓통하여 빨아들인 데이터를 쓰기
        byte[] buf = new byte[1024];

        while(true){
            int len = is.read(buf);
            if(len == -1){break;}
            fos.write(buf, 0, len);
        }

👆 코드를 분석해보자

  1. 클라이언트가 서버에게 파일을 전달 받는것.
  2. 클라이언트이기 때문에 ServerSokect이 아니라 socket생성.
  3. 소켓으로 오는 데이터를 InputStream을 통해서 받고, 받은 데이터를 FileOutputStream으로 파일 복제



3. 서버에서 클라이언트로 파일이 흘러가는 순서도



4. 포츈추키 클라이언트 - 서버 만들기

  • 공통되는 클래스(포춘쿠키 뽑기)
public class FortuneTeller {

    public String [] arr = {"대길","소길","대흉","소흉"};

    public String fortune(){
        Random rand = new Random();
        int index = rand.nextInt(arr.length);
        return arr[index];
    }

  • Server
public class FortuneServer {
    public static void main(String[] args) throws Exception{
        FortuneTeller fortuneTeller = new FortuneTeller();
        ServerSocket serverSocket = new ServerSocket(5555);
        System.out.println("ready ----------------");

       while(true){
           Socket socket = serverSocket.accept();
           System.out.println("Accepted connection from " + socket.getInetAddress());
           OutputStream outputStream = socket.getOutputStream(); //소켓에 OutPut빨대 연결
           DataOutputStream dataOutputStream = new DataOutputStream(outputStream); //데이터를 더 쉽게 연결

           String text = fortuneTeller.fortune();

           dataOutputStream.writeUTF(text); //DataOut을 사용한 문자열 text를 UTF서버로 전송
           dataOutputStream.flush(); //버퍼에 출력스트림으로 보내고 버퍼를 비우는역할
           dataOutputStream.close();
           socket.close();
       }

  • Client
public class FortuneClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 5555);

        InputStream in = socket.getInputStream();
        DataInputStream dis = new DataInputStream(in);

        String fortune = dis.readUTF(); //UTF로 읽기
        System.out.println(fortune);

        dis.close();
        socket.close();
    }

  • Web
public class FortuneWeb {
    public static void main(String[] args) throws Exception {

        FortuneTeller teller = new FortuneTeller();

        ServerSocket serverSocket = new ServerSocket(5555);
        System.out.println("ready-------------------");

        while (true) {
            try(Socket socket = serverSocket.accept();
                OutputStream out = socket.getOutputStream();){

                String msg = teller.fortune();

                out.write(new String("HTTP/1.1 200 OK\r\n").getBytes());

                out.write(new String("Cache-Control: private\r\n").getBytes());
                out.write(new String("Content-Length: "+msg.getBytes("UTF-8").length+"\r\n").getBytes());
                out.write(new String("Content-Type: text/html; charset=UTF-8\r\n\r\n").getBytes());

                out.write(msg.getBytes(StandardCharsets.UTF_8));
            }
        }
    }
}



5. 비지속형서버 / 지속형서버

👉 지속형서버의 예시는 게임 (서버농장)
👉 비지속형서버는 많은 서버가 아니더라도 많은 사람들을 유치가능

0개의 댓글