eotpan
1k
2019-03-29 15:27:02
17
221

스프링 웹소켓 질문드려요 (서버에서 클라이언트로 바로 메세지 전송이 가능한가요?)



스프링 웹소켓 예제들을 보면 (sockjs사용)


jsp에서 메세지를 보내고.. 그걸 접속한 브라우저에서 뿌려주는 방식이더라고요?


jsp에서는 


        // 서버로부터 메시지를 받았을 때

        function onMessage(msg) {

               var data = msg.data;

               $("#data").append(data + "<br/>");

        }


위 같은 코드만 있고


서버에서 직접 클라이언트로 메세지를 보낼수도 있나요?


브라우저 접속해서 강제로 보낸 메세지를 뿌린다면 ajax폴링이랑 다를게 별로 없어보여서요.(물론 폴링과 같다는 얘긴 아니고요)


아무튼 jsp에서 특정 동작이 없어도 스프링(java)에서 바로 클라이언트에 메세지 보내는것이 가능한지 궁금합니다.


참고한 예제 https://victorydntmd.tistory.com/253


예제를 보면 sendMessage가 동작할때.... 메세지가 브로드 캐스팅 됩니다..


이같은 동작 없이. 바로 스프링에서 직접 호출하고싶습니다..


조언 부탁드립니다. 




0
0
  • 답변 17

  • 유리세계
    884
    2019-03-29 15:32:41

    웹소켓을 이용하시려면 결국에 서버관리자로서의 역할을 처리할 수 있는 클라이언트가 있어야 할거에요...

    0
  • 배우고싶은이
    455
    2019-03-29 15:36:44

    당연히 되죠.. 그럴려고 웹소켓 쓰는거 아닌가요?

    웹소켓 이용한 챗팅만 봐도 나는 아무런 액션을 안하고 있어도(ajaxt polling 없음) 대화상대가 입력한 것이 화면에 뜨잖아요..

    0
  • BiFOS
    24
    2019-03-29 15:48:38


    List<WebSocketSession> wsSessionList = wsHandler.getSessionList();
    for (WebSocketSession wsSess : wsSessionList) {
    	try{
    		wsSess.sendMessage(new TextMessage(entity.toString()));
    		logger.info(entity.toString());
    	} catch (Exception e) {
    
    	}
    }

    저도 궁금해서 이것저것 찾아봤는데요

    1. 웹소켓 핸들러의 웹소켓 세션리스트를 가져온다.

    2. 웹소켓 세션을 반복문으로 돌면서 보내고 싶은메시지를 sendMessage로 보낸다.


    위와 같은 방법으로 저는 해결했습니다 도움이 되셨으면 좋겠네용

    0
  • eotpan
    1k
    2019-03-29 15:49:07

    유리세계 / 그말은.. 즉.. 브로드 캐스팅할 jsp가 필요하다는 말인가요?


    실시간 쪽지 알림을 예로 들면..

    쪽지를 쓴 주체가... 마지막으로 jsp가 호출되어서

    그 jsp에서 위구문으로 소켓을 맺고.. 해당 쪽지수신자의 세션을 찾아서

    브로드 캐스팅 해줘야된다는 말씀이신가요?


    저는 jsp에 안가고 스프링 java소스 내에서 직접 구현이 가능한지 이부분이 궁금해서요^^

    답변감사합니다.



     

    배우고싶은이 / 되면 방법좀 알려주세요. ㅠㅠ..


    제가 원하는건 자바소스에서.. 직접 가능하냐는 겁니다 물론 폴링이랑 다르죠.. 




    0
  • eotpan
    1k
    2019-03-29 15:50:44

    BiFOS /

    답변감사합니다.

    제가 찾은 소스도 저렇게 되어있습니다 ^^


    제말은 jsp로 가지 않고 위 소스를 서버에서 강제로 특정동작후에...

    호출할수 있는지가 궁금합니다..





    0
  • BiFOS
    24
    2019-03-29 15:52:44

    특정동작이 예를 들면 어떤것인지 알아야할것같습니다..


    저는 다른쓰레드에서 돌고 있는 app 실행중에 메시지를받으면

    웹소켓으로 jsp에 받게 되어있거든요..


    자바코드로 바로 웹소켓으로 메시지 전달하구있습니다

    0
  • eotpan
    1k
    2019-03-29 15:53:41

    BiFOS // 아 답변감사합니다.. ~ 제가 뭔가 잘못봤네요

    지금 적용해보고 올게요 ^^

    0
  • BiFOS
    24
    2019-03-29 15:55:19
    넵! 도움이 되셨으면 좋겠습니다~
    0
  • eotpan
    1k
    2019-03-29 15:56:59

    BiFOS 님

    wsHandler.getSessionList()


    위함수좀 보여주실수있나요 ㅠㅠ?

    0
  • eotpan
    1k
    2019-03-29 16:35:07 작성 2019-03-29 16:49:26 수정됨

    BiFOS 님


    일단 간단하게..컨트롤러에서 브로드캐스팅 해주는거 만들어봤는데..


           private ConnUserCountHandler connUserCountHandler;

    @RequestMapping(value="/sys/main/testSocket.do")

    public void testSocket() throws Exception {


    List<WebSocketSession> wsSessionList = connUserCountHandler.getSessionList();

    for (WebSocketSession wsSess : wsSessionList) {

    try{

    wsSess.sendMessage(new TextMessage("555" )); // 접속자수..

    //wsSess.sendMessage(new TextMessage(entity.toString()));

    //logger.info(entity.toString());

    } catch (Exception e) {


    }

    }

        }



    위처럼했습니다../sys/main/selectMainView.do 호출시..

    test로 전 메인화면 보고있는 접속자에게 555를 보내려 하는데..


    ConnUserCountHandler는 아래와같습니다..

    public class ConnUserCountHandler extends TextWebSocketHandler { protected Log log = LogFactory.getLog("com.silk"); private List<WebSocketSession> sessionList = new ArrayList<WebSocketSession>(); // 클라이언트와 연결 이후에 실행되는 메서드 @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { sessionList.add(session); System.out.println("{"+session.getId()+"} 연결됨" ); } // 클라이언트가 서버로 메시지를 전송했을 때 실행되는 메서드 @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { System.out.println("{"+session.getId()+"}로 부터 {"+ message.getPayload()+"} 받음"); //System.out.println("접속자수:"+result.size()); for (WebSocketSession sess : sessionList) { sess.sendMessage(new TextMessage(""+sessionList.size())); } } // 클라이언트와 연결을 끊었을 때 실행되는 메소드 @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { sessionList.remove(session); System.out.println("{"+session.getId()+"} 연결 끊김" ); } public List<WebSocketSession> getSessionList() throws Exception { return sessionList; } }


    저는

    connUserCountHandler.getSessionList()

    이렇게 호출할떄 널포인터가 나는데 ㅠㅠ


    님 소스 올려주신거보면

    wsHandler 객체를 어떻게 가져오셧는지가 궁금합니다...


    조언 부탁드립니다.

    0
  • 배우고싶은이
    455
    2019-03-29 17:01:22

    <beans:bean id="connUserCountHandler " class="XXX.XXX.XXXX.ConnUserCountHandler " />


    서블릿 컨텍스트 설정에서 bean으로 등록 합니다.


    컨트롤러에서는 @Autowired로 주입받아서 씁니다.

    0
  • eotpan
    1k
    2019-03-29 17:11:17

    배우고싶은이 / 감사합니다


    오토와이어드만 했고.. 빈등록을 안했네요.. 오토스캔이 되어있어서 읽어올줄알았는데

    안되었나와요...  빈등록해주니까


    객체는 가져와지는데. ㅠㅠ..

    세션리스트에 0이 나오네요 분명 1명이 접속했는데... 흠.. 

    0
  • 배우고싶은이
    455
    2019-03-29 17:14:31 작성 2019-03-29 17:16:03 수정됨

    전 해본것만 얘기하는 편입니다.


    <websocket:handlers>

    <websocket:mapping handler="echoHandler" path="/echo" />

    <websocket:sockjs />

        </websocket:handlers>


    설정되어 있나요? 웹소켓 핸들러패스..

    해당 패스로 들어와야 핸들러가 동작하고 session등록 할겁니다.

    controller의 requestmapping url에 맞춰주세요.

    저는 똑같이 서블릿 컨택스트 설정 파일에 추가 했습니다.


    아 그리고 첨에 된다고만 얘기한것은 질문자체가 

    '서버에서 클라이언트로 바로 메세지 전송이 가능한가요?'


    로 되어 있어서 였습니다. 

    가능한가요? -> 네 가능합니다.

    0
  • eotpan
    1k
    2019-03-29 17:20:19

    배우고싶은이

    댓글감사합니다~~ 


    위 설정은..WebSocketConfig.java에 되어있는데..

    @Configuration

    @EnableWebSocket

    public class WebSocketConfig implements WebSocketConfigurer {

    @Override

        public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {

            registry.addHandler(new ConnUserCountHandler(), "/connUserCount").setAllowedOrigins("*").withSockJS();        


    }


    자바에 명시해서쓰고있습니다.. 다른거는 다 동작하는데.

    jsp에서 브로드캐스팅시... 타 브라우저로 접속자 보여주는거 잘됩니다만..

    개발 편의상 컨트롤러에서 /sys/main/testSocket.do 접속시 브로드캐스팅 해주고 싶은데

    이게 안되네요 ㅠㅠ



    @RequestMapping(value="/sys/main/testSocket.do")

    public void testSocket() throws Exception {


    System.out.println("->"+connUserCountHandler);

    List<WebSocketSession> wsSessionList = connUserCountHandler.getSessionList();

    System.out.println("->"+wsSessionList.size());

    for (WebSocketSession wsSess : wsSessionList) {

    System.out.println("->"+wsSess.getId());

    try{

    wsSess.sendMessage(new TextMessage("555" )); // 접속자수..

    //wsSess.sendMessage(new TextMessage(entity.toString()));

    //logger.info(entity.toString());

    } catch (Exception e) {


    }

    }

        }


    뿌려보면 세션리스트가 0으로 나오네요


    실제 접속시에는.... 접속자수 카운트 잘됩니다..

    컨트롤러에서 555찍을때.... 안되는데


    제가 지금 하는방법이 맞긴 맞는거죠? ㅎㅎ? 이거 구글에 처도 잘 안나오는거같아서 ㅠㅠ..

    키워드를 뭐로 검색해야할지... 

    0
  • eotpan
    1k
    2019-03-29 17:33:05

    System.out으로 찍어보니  컨트롤러서 찍은 connUserCountHandler 주소와

    ConnUserCountHandler 클래스 내에서 this 를 찍어보니 주소가 둘이 다르네요...;;



    0
  • 배우고싶은이
    455
    2019-03-29 17:37:20

    핸들러 URL을 달리해서는 해보지 않았습니다.


    일단 생각에는 해들러에 맵핑된 connUserCount 주소로 들어오면

    afterConnectionEstablished -> 실행


    사용자가 해당 페이지를 떠나면 (connUserCount 가 아닌곳)

    afterConnectionClosed -> 실행


    이렇게 될듯한데요.


    크로브라우져 프라이빗 모드로 여러개 띄우고 각각 접속해서 확인해보시면 어느시점에 session.remove 되는지 확인 가능할듯 하네요.


    여러가지로 테스트 해보셔야 할듯..


    성공하시길 빕니다.


    0
  • 더미
    11k
    2019-03-30 18:43:29

    페이지이동하면 웹소켓끊어집니다.

    0
  • 로그인을 하시면 답변을 등록할 수 있습니다.