배움 __IL/TIL 1기

TIL : 35번째- 230116 [1-3-월]

Mo_bi!e 2023. 1. 16. 18:23

I. 웹소켓 해보기

MDN 웹소켓!

web에서 제공하는 api 중에 하나이다.

 

여기서 소켓이란 A,B 컴퓨터 두곳 간의 정보를 주고 받기위한 최소한의 정보이고 

전구도 꽂는 소켓이고(물리적장치), 어떤성분이 있어야 주고받을 수있어야할까?

 

우편물은 주소, 사서함번'호', 

건물이 IP / 건물 안의 SW들 이것이 데이터 받기위한 버퍼(식별자 == 포트번호)가 있어야한다

그래야 API를 보내거나 받을 수 있다

 

그러나 웹소켓은 두가지 정보가 아니라 세가지이다(웹이라서)

IP + port + "URL" 이다

당연히 internet이지만 web이라는 포토로콜로 하기 때문에 웹기반 소켓이라고 하고, 웹의정보,리소스가 추가됨

최근 websocket로 데이터를 주고받는다.

 

1. 웹소켓 객체 생성

mdn 에 보면 구문에 url 을 인수로 넣어준다

 

(1) 기본 세팅하기

<index.html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <link href="chat.css" rel="stylesheet" type="text/css">

    <script src="index.js"></script>

</head>
<body>


    <div class ="chat">
        <div class="chat-list">
            <input class="btn-conn" type="button" value="서버연결">

        </div>

        <div class = "chat-input">
            <input class="input-send">
            <input class="btn-send" type="button" value="전송">
        </div>

    </div>


</body>
</html>

 

<chat.css>

.chat{
    width: 300px;
    height: 700px;
    padding: 10px;
    box-sizing: border-box;
    background-color: aliceblue;
}

.chat-list{
    height: 500px;
    width: 100%;
    border: 1px solid #e9e9e9;
    background-color: white;
}

 

<index.js>

window.addEventListener("load",function(){

    let inputSend = this.document.querySelector(".input-send");
    let btnsend = this.document.querySelector(".btn-send");
    let btnconn = this.document.querySelector(".btn-conn");


    btnconn.onclick = function(e){
        
        // WebSocket 연결 생성
        let username = 'newlec';
        const socket = new WebSocket(`ws://localhost:8080/chat/${username}`);

        // 연결이 열리면
        socket.addEventListener('open', function (event) {
            socket.send('Hello Server!');
        });

        // 메시지 수신
        socket.addEventListener('message', function (event) {
            console.log('Message from server ', event.data);
        });

        
        console.log("connect...");
    }


    btnsend.onclick = function(e){
        let msg = inputSend.value;
        console.log(msg);

    }
});

소켓을 생성하고,

oepn message 관련 이벤트함수를 만든다.

 

(2) 소켓

1)

연결을 유지 하는 것이다.

연결은 방송국에서 우편물을 한 사서함으로 받는다 전용이 아니라 공유 포트로 다 받음

이 경우 누구한테 온지 몰라서 다 열어봐야함

 

소켓TCP IP 기반이다

이는 클라이언트가 보내는 포트가 전용사서함이 따로 준비된다

여기 쌓이는 편지는 홍길동에게만 온다.

 

실질적 연결이 아니라 홍길동에다가 전송데이터 넣을시 홍길동에게만 간다

전용포트를 가지고 있기때문에 내가 넣으면 가고 개가 넣으면 온다

이런경우 전용포트 자체가 연결되어있다고 함

결국 포트(사서함)이 끊어지면 연결이 끊어진 것이다.

그래서 우리가 연결형을 담당하고 있는 TCP - IP 는 전용포트이다

 

한편 UDP는 공용포트, 공용사서함이다

 

만약에 채팅서버 이용시 접속자가 100명이면 사서함은 101개이다.

왜냐하면 서버포트가 한개 더 있기 때문이다.(추후에...)

 

 

2) 소켓연결 실습

    btnconn.onclick = function(e){
        
        // WebSocket 연결 생성
        const socket = new WebSocket('ws://localhost:8080/');

        // 연결이 열리면
        socket.addEventListener('open', function (event) {
            socket.send('Hello Server!');
        });

        // 메시지 수신
        socket.addEventListener('message', function (event) {
            console.log('Message from server ', event.data);
        });

        
        console.log("connect...");
    }

8800뒤에 /game /chat 등으로 필요에 따라서 할 수있다.

80은 쓰지않아도 되지만 8080인 경우에는 써주어야한다

 

btnconn.onclick = function(e){
        
        // WebSocket 연결 생성
        let username = 'newlec';
        const socket = new WebSocket(`ws://localhost:8080/chat/${username}`);
}

backtick으로 해준다.

chat 로하자

 

(3) 자바에서 설정하기

1)

package com.newlecture.web;

import jakarta.websocket.server.ServerEndpoint;

@ServerEndpoint("/char/{username}")
public class CharServer {

	
}

이 경우 서블릿과 이클립스간 연결을 다시 시도 해야한다

지난번에 포트번호를 8080이 아니라 80으로 했다 양지해두자

 

 

2) 문제가 발생

 

문제가 발생했다.

그 이유는 첫번째 context root 문제이다.

 

JS에서

포트가 80이면 port번호 설정이 필요가 없으나, 8080이면 별도로 넣어주어야한다.

Websocket의 urllocalhost 다음에 contextroot를 해주어야한다.

 

이클립스에서

만약 contextroot를 삭제한다면 다음과 같은 절차를 해야한다

우선 서버remove한뒤 프로젝트clear을 한다.

그리고 add and remove프로젝트 파일을 올린다

그리고 start를 한다.

 

두번째 문제로

openHandler 문제이다.

 

 

 

(4) 백과 프론트 메시지 주고받기

<백>

package com.newlecture.web;

import org.apache.tomcat.util.buf.MessageBytes;

import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.ServerEndpoint;

@ServerEndpoint("/chat")
public class ChatServer {

	//open
	@OnOpen
	public void openHandler(Session session) {
		System.out.println("connected from ???");
		//
	}
	
	//반대편에서 연결받았다는 메시지
	//MESSAGE
	@OnMessage
	public void messageHandler(Session session, String message) {
		System.out.println(message);
	}
	
	
	//CLOSE
	
}

onoepn의 경우와 onmessage의 경우 각각을 오바리이딩 해주어야한다.

여기서 Session이 무엇인지 궁금하다.

 

<front>

window.addEventListener("load",function(){

    let inputSend = this.document.querySelector(".input-send");
    let btnsend = this.document.querySelector(".btn-send");
    let btnconn = this.document.querySelector(".btn-conn");

    let socket = null;

    btnconn.onclick = function(e){
        // ${username}
        // WebSocket 연결 생성
        let username = 'newlec';
        // socket = new WebSocket(`ws://localhost/chat`);
        socket = new WebSocket(`ws://192.168.5.8/chat`);

        // 연결이 열리면
        socket.addEventListener('open', function (event) {
            socket.send('Hello Server!');
        });

        // 메시지 수신
        socket.addEventListener('message', function (event) {
            console.log('Message from server ', event.data);
        });

        
        console.log("connect...");
    }


    btnsend.onclick = function(e){
        let msg = inputSend.value;
        console.log(msg);

        //null 이 아니면
        if(socket){
            socket.send(msg);
        }



    }
});

위와같이 socket의 주소를 받아서 연결이 가능하다.

 

(5) 돌려주기

걔한테만 돌려주면 eco(되돌려주기), 전체에게 뿌려주면 chating이 된다

 

이 경우 동시에 뿌릴때 컬렉션,메시지 구성, 필터링 접속한 얘가 12명인데 방을 나누기가 있다

이러한 세부적인것은 점점 어렵다

 

동시성에서 줄세우는 동기화가 중요하다

@ServerEndpoint("/chat")
public class ChatServer {

	static CopyOnWriteArrayList<Session> sessions = new CopyOnWriteArrayList<>();	
	//open
	@OnOpen
	public void openHandler(Session session) {
		System.out.println("connected from ???");
		//
		
		
	}

 

static CopyOnWriteArrayList<Session> sessions = new CopyOnWriteArrayList<>();

이거를 하면 동시성을 해결할 수있다.

 

 

한편 이렇게 하면 다같이 채팅하는것등을 동시에 볼 수가 있다.

	@OnMessage
	public void messageHandler(Session session, String message) throws IOException {
		System.out.println(message);
		
		for(Session s : sessions)
			s.getBasicRemote().sendText(message);
	}

 

 

(6) 서버 닫힌거 알려주기

	@OnClose
	public void closeHandler(Session session) {
		sessions.remove(session);
	}

서버가 닫혔을 때 세션을 지운다(remove).

 

 


1. 보충

(1) 스타크래프트와 tcp udp

스타그래프트에서 LAN의 방식으로 UDP를 한다

 

UDP TCP는 네트와크 프로토콜이다.

여기서 UDP(user datagram protocol)이다. 여기서 중요시 하는것은 속도이다.

TCP(transmissin Control protocol)은 중요시 하는것이 안정성 신뢰성이다.

 

1)

UDP 의 속도가 빠른이유는 일방향통신이다. 그렇기 때문에 상대방이 제대로 들었는지 확인하지 않는다

2)

TCP는 안정적인 이유가 답신을 하기 때문이다. 답신의 방법과 관련해서 three-way handshake , four-way handshake가 있다.

 

 

 

 

 

(2) session

What (정의) : 서버의 상태정보 유지기술을 의미한다.(클라이언트의 상태정보 유지기술은 쿠키) 이 경우 세션은 클라이언트별 각각 상태정보를 서버에 저장한다

Why (존재이유) : 클라이언트 별 세션ID부여하고 저장 위해서

How (방법) : 

예 : 로그인 상태 유지되기

 

2. 회고 

1) 아직 백과 프론트의 연결에 대한 명확한 느낌이없다. 그냥 따라친 느낌에 불과하고, 실제로 서로연결에 대한 알림이나 통신 커뮤니케이션 기능의 작동만 느껴진다. 어서빨리 원리를 알아서 상호 유기적인 느낌을 체감하고싶다.

 

'배움 __IL > TIL 1기' 카테고리의 다른 글

TIL : 37번째- 230125 [1-4-수]  (0) 2023.01.25
TIL : 36번째- 230117~20 [1-3-화~금]  (0) 2023.01.23
TIL : 34번째- 230113 [1-2-금]  (0) 2023.01.13
TIL : 33번째- 230112 [1-2-목]  (0) 2023.01.12
TIL : 32번째- 230111 [1-2-수]  (0) 2023.01.11