标签: spring-websocket

在Spring Websocket上向特定用户发送消息

如何仅从服务器向特定用户发送websocket消息?

我的webapp具有弹簧安全设置并使用websocket.我遇到了一个棘手的问题,试图从服务器向特定用户发送消息.

我阅读本手册的理解来自我们可以做的服务器

simpMessagingTemplate.convertAndSend("/user/{username}/reply", reply);
Run Code Online (Sandbox Code Playgroud)

在客户端:

stompClient.subscribe('/user/reply', handler);
Run Code Online (Sandbox Code Playgroud)

但我永远无法调用订阅回调.我尝试了许多不同的路径,但没有运气.

如果我将它发送到/ topic/reply它可以工作,但所有其他连接的用户也会收到它.

为了说明问题,我在github上创建了这个小项目:https://github.com/gerrytan/wsproblem

重现步骤:

1)克隆并构建项目(确保您使用的是jdk 1.7和maven 3.1)

$ git clone https://github.com/gerrytan/wsproblem.git
$ cd wsproblem
$ mvn jetty:run
Run Code Online (Sandbox Code Playgroud)

2)导航到http://localhost:8080,使用bob/test或jim/test登录

3)单击"请求用户特定消息".预期:仅对此用户的"仅收到消息给我"旁边显示消息"hello {username}",实际:未收到任何消息

java spring spring-mvc spring-websocket

72
推荐指数
2
解决办法
5万
查看次数

使用Websockets代替RESTful HTTP的缺陷是什么?

我目前正在开发一个项目,要求客户端请求大量工作并将其发送到服务器.然后,服务器将作业分开并响应一组URL,以便客户端进行GET调用并回送数据.我是该项目的新手,我目前正在使用Spring websockets来提高效率.而不是客户端不断ping服务器以查看它是否已准备好返回结果,websocket现在只需直接联系客户端万岁!

让websockets从头到尾管理整个过程是不是一个坏主意?我正在使用带有Spring websockets的STOMP,是否仍然存在抛弃REST的主要问题?

rest client-server http websocket spring-websocket

57
推荐指数
2
解决办法
2万
查看次数

我应该在80以外的端口上使用WebSocket吗?

我应该在非80端口上使用WebSocket吗?它是否会毁掉使用现有Web/HTTP基础架构的整个目的?我认为它不再符合非80端口上的Web Socket 名称.

如果我在其他端口上使用WebSocket,为什么不直接使用TCP呢?或者WebSocket协议本身有什么特别的好处吗?

由于当前的WebSocket握手是HTTP UPGRADE请求的形式,这是否意味着我必须在端口上启用HTTP协议,以便可以完成WebSocket握手?

websocket spring-websocket

56
推荐指数
2
解决办法
8万
查看次数

WebSocket服务器如何处理多个传入连接请求?

根据这里:

HTTP Upgrade标头请求服务器将应用层协议从HTTP切换到WebSocket协议.

客户端握手在IE10和服务器之间建立了HTTP-on-TCP连接.在服务器返回其101响应之后,应用层协议从HTTP切换到使用先前建立的TCP连接的WebSockets.

此时HTTP完全脱离了图片.使用轻量级WebSocket线协议,任何端点现在都可以随时发送或接收消息.

所以,我的理解是,在第一个客户端完成与服务器的握手后,服务器的80端口将被WebSocket协议垄断.并且HTTP不再在80端口上运行.

那么第二个客户端如何与服务器交换握手.所有WebSocket握手都是HTTP格式.

添加1

谢谢你到目前为止的所有答案.他们真的很有帮助.

现在我明白同一台服务器的80端口是由多个连接共享TCP.这种共享完全没问题,因为TCP连接是由5元素元组标识Jan-Philip Gehrcke出来的.

我想补充几点想法.

这两个WebSocketHTTP仅仅是应用层协议.通常他们都依赖TCP协议作为他们的运输.

为什么选择80端口?

WebSocket设计有意为握手和后续通信选择服务器的端口80 .我认为设计人员希望从传输级别的角度 WebSocket通信看起来像普通的HTTP通信(即服务器端口号仍然是80).但根据jfriend00答案,这个技巧并不总是欺骗网络基础设施.

协议如何从HTTP转移到WebSocket

来自RFC 6455 - WebSocket协议

基本上,考虑到Web的限制,它应尽可能地将原始TCP暴露给脚本.它的设计也使其服务器可以与HTTP服务器共享一个端口,使其握手成为有效的HTTP升级请求.可以在概念上使用其他协议来建立客户端 - 服务器消息传递,但WebSockets的目的是提供一个相对简单的协议,该协议可以与HTTP和部署的HTTP基础结构(例如代理)共存,并且尽可能安全地接近TCP.在给定安全性考虑的情况下使用此类基础结构,通过有针对性的添加来简化使用并简化简单事务(例如添加消息语义).

所以我认为我在下面的陈述中错了:

握手请求模仿 HTTP请求,但后面的通信没有.握手请求到达端口80上的服务器. 由于它是80端口,服务器将使用HTTP协议对其进行处理.这就是为什么WebSocket握手请求必须是HTTP格式的原因. 如果是这样,我认为必须修改/扩展HTTP协议以识别那些特定于WebSocket的东西.否则它将无法实现它应该屈服于 WebSocket协议.

我认为应该这样理解:

WebSocket通信以从客户端到服务器的有效 …

http websocket spring-websocket

55
推荐指数
3
解决办法
4万
查看次数

Spring WebSocket @SendToSession:向特定会话发送消息

是否可以向特定会话发送消息?

我在客户端和Spring servlet之间有一个未经验证的websocket.当异步作业结束时,我需要向特定连接发送未经请求的消息.

@Controller
public class WebsocketTest {


     @Autowired
    public SimpMessageSendingOperations messagingTemplate;

    ExecutorService executor = Executors.newSingleThreadExecutor();

    @MessageMapping("/start")
    public void start(SimpMessageHeaderAccessor accessor) throws Exception {
        String applicantId=accessor.getSessionId();        
        executor.submit(() -> {
            //... slow job
            jobEnd(applicantId);
        });
    }

    public void jobEnd(String sessionId){
        messagingTemplate.convertAndSend("/queue/jobend"); //how to send only to that session?
    }
}
Run Code Online (Sandbox Code Playgroud)

正如您在此代码中看到的,客户端可以启动异步作业,当它完成时,它需要结束消息.显然,我只需要向申请人发送信息而不是向所有人广播.有一个@SendToSession注释或messagingTemplate.convertAndSendToSession方法会很棒.

UPDATE

我试过这个:

messagingTemplate.convertAndSend("/queue/jobend", true, Collections.singletonMap(SimpMessageHeaderAccessor.SESSION_ID_HEADER, sessionId));
Run Code Online (Sandbox Code Playgroud)

但这会向所有会话广播,而不仅仅是指定的会话.

更新2

使用convertAndSendToUser()方法进行测试.这个测试是和正式的Spring教程的破解:https://spring.io/guides/gs/messaging-stomp-websocket/

这是服务器代码:

@Controller
public class WebsocketTest {

    @PostConstruct
    public void init(){
        ScheduledExecutorService statusTimerExecutor=Executors.newSingleThreadScheduledExecutor();
        statusTimerExecutor.scheduleAtFixedRate(new Runnable() …
Run Code Online (Sandbox Code Playgroud)

java spring stomp spring-mvc spring-websocket

36
推荐指数
1
解决办法
2万
查看次数

Spring @SubscribeMapping是否真的为客户订阅某个主题?

我正在使用Spring Websocket和STOMP,Simple Message Broker.在我的@Controller使用方法级别@SubscribeMapping,它应该将客户端订阅到主题,以便客户端之后将接收该主题的消息.假设客户订阅主题"聊天":

stompClient.subscribe('/app/chat', ...);

当客户订阅"/ app/chat "而不是"/ topic/chat"时,此订阅将转到使用以下方法映射的方法@SubscribeMapping:

@SubscribeMapping("/chat")
public List getChatInit() {
    return Chat.getUsers();
}
Run Code Online (Sandbox Code Playgroud)

这是Spring ref.说:

默认情况下,@ SubsscribeMapping方法的返回值作为消息直接发送回连接的客户端,并且不通过代理.这对于实现请求 - 回复消息交互很有用; 例如,在初始化应用程序UI时获取应用程序数据.

好的,这就是我想要的,但只是部分 !! 订阅后发送一些init-data,好吧.但订阅呢?在我看来,这里发生的事情只是一个请求 - 回复,就像一个服务.订阅只是消费.如果是这种情况,请澄清我.

  • 如果经纪人没有参与此活动,客户是否订阅了某些地方?
  • 如果以后我想向"聊天"下标者发送一些消息,客户会收到它吗?它似乎不是这样.
  • 谁真正实现了订阅?经纪人?或者其他人?

如果在这里客户端没有订阅任何地方,我想知道为什么我们称之为"订阅"; 因为客户端只收到一条消息而不是后续消息.

编辑:

为了确保订阅已经实现,我尝试的内容如下:

服务器端:

组态:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/hello").withSockJS();
    } …
Run Code Online (Sandbox Code Playgroud)

spring stomp messagebroker spring-messaging spring-websocket

35
推荐指数
4
解决办法
2万
查看次数

与iOS和Android客户端连接到SockJS后端

我正在使用Spring WebSockets开发WebSocket消息传递后端,它使用SockJS + STOMP协议.不使用普通WebSockets的原因是因为我需要利用SockJS在Spring WebSockets中提供的安全集成以及SockJS的其他整洁功能,例如房间,订阅等.我想知道这是否是一个很好的选择这样移动(iOS和Android)和Web客户端应用程序可以轻松连接到后端服务器并执行消息传递.如果是,那么我可以用于iOS和Android的库.

SockJS GitHub页面上,他们还列出了可用的客户端库,但没有iOS和Android.所以,我想知道SockJS是否因此而值得使用.

我发现对于iOS客户端Primus-Objc(GitHub页面)库声称它们可以连接到那native WebSockets, Socket.IO, SockJS or perhaps engine.io.是一个真正的声明吗?事件如果是真的那么,那个图书馆的质量怎么样?

事件如果可以在后面使用SockJS,那么是否也可以显示iOS和Android的示例代码,以便我可以在移动设备上执行概念验证?

如果SockJS对我来说不是一个好选择,那么用Socket.io + Node.js构建我的消息传递应用程序会更好(使用JavaScript).在我看来,Socket.io有所有需要的iOS客户端库(Socket.IO的官方库)和Android(Socket.IO的官方库).

另一种选择可以是使用Netty-Socket.io库并手动构建每个端点,而无需Spring Framework(我正在考虑使用)的任何帮助,但是我需要解决的是小问题,即安全问题.实际上有人已经尝试过这样做(同一位作者在Netty-Socket.IO Github官方网页上提问),但看起来他还没有运气解决它.

java spring android ios spring-websocket

31
推荐指数
2
解决办法
9090
查看次数

连接到websocket时我得到状态200,但这是一个错误?

我的错误显示在浏览器的控制台中:

"WebSocket connection to 'ws://localhost:32768/DspClusterWebServices/myHandler' failed: Unexpected response code: 200"

我正在使用Spring Websockets 4.1.5Tomcat 8.0.18.我的WebSocketConfigurer实现类如下所示:

@Configuration
@Controller
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer
{
   class MyHandler implements WebSocketHandler
   {
      @Override
      public void afterConnectionEstablished(WebSocketSession session) throws Exception
      {
         System.out.println("afterConntectionEstablished called");
      }

       ...implements rest of functions with a System.out.println and false for supportsPartialMessages()

      }
   }

   @Override registerWebSocketHandlers(WebSocketHandlerRegistry registry)
   {
      registry.addHandler(myHandler(), "myHandler").withSockJS();
   }

   @Bean
   public WebSocketHandler myHandler()
   {
      return new MyHandler();
   }
}
Run Code Online (Sandbox Code Playgroud)

我的testWebsocketClient.js尝试连接此代码,但错误代码为200:

websocket = new WebSocket("ws://localhost:8080/myApp/myHandler");
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚下一步该尝试什么.我以为这会导致afterConnectionEstablished(WebSocketSession会话)方法被触发?代码200不好吗?

javascript java tomcat websocket spring-websocket

30
推荐指数
4
解决办法
5万
查看次数

如何使用Spring-websocket基于用户权限拒绝主题订阅

我正在实现一个版本的股票应用程序,其中服务器能够根据用户权限拒绝特定主题的主题订阅.spring-websocket有没有办法做到这一点?

例如:

在库存示例项目中我们有3个仪器的价格主题:Apple,Microsoft,Google并且有两个用户:User1,User2

User1应该可以访问Apple,Microsoft User2应该只能访问Google

如果User1订阅Google,他应该被拒绝回复,之后不应该向他广播消息.

spring spring-security publish-subscribe websocket spring-websocket

27
推荐指数
2
解决办法
6645
查看次数

Wildfly中的Spring Boot Websockets

嗨,我需要将我的Spring Boot应用程序部署到Wildfly 8.1中,我遇到以下异常:

引起:java.lang.RuntimeException:java.lang.ClassCastException:org.apache.tomcat.websocket.server.WsServerContainer无法转发到io.undertow.servs.core.DeploymentManagerImpl的io.undertow.websockets.jsr.ServerWebSocketContainer.部署(DeploymentManagerImpl.java:219)org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:87)org.wildfly.extension.undertow.deployment.UndertowDeploymentService.start(UndertowDeploymentService.java:72) at org.jboss.msc.service.ServiceControllerImpl $ StartTask.startService(ServiceControllerImpl.java:1948)[jboss-msc-1.2.2.Final.jar:1.2.2.Final] at org.jboss.msc.service.ServiceControllerImpl $ StartTask.run(ServiceControllerImpl.java:1881)[jboss-msc-1.2.2.Final.jar:1.2.2.Final] ... 3更多引起:java.lang.ClassCastException:org.apache.tomcat. websocket.server.WsServerContainer无法转发到io.undertow.websockets.jsr.Bootst的io.undertow.websockets.jsr.ServerWebSocketContainer rap $ WebSocketListener.contextInitialized(Bootstrap.java:69)at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:173)at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:190) ......还有7个

似乎我的websockets和消息传递的设置可能是罪魁祸首?我正在看这个https://github.com/joshlong/boot-examples/issues/2并没有提出的解决方案似乎适合我.这是我的pom的依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.1.6.RELEASE</version>
</parent>

<dependencies>

    <!--Testing-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>${apache.httpcomponents.version}</version>
    </dependency>

    <!-- Spring -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-websocket</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-messaging</artifactId>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring4</artifactId>
    </dependency>
    <dependency> …
Run Code Online (Sandbox Code Playgroud)

spring websocket wildfly spring-boot spring-websocket

25
推荐指数
3
解决办法
2万
查看次数