当前位置: 首页 > 知识库问答 >
问题:

spring tcp套接字,授权客户端并处理挂起的响应

应志用
2023-03-14
  • 根据唯一标识符(例如,从客户端接收的客户端机密,可能使用TCP连接事件)授权客户端
  • 直接向特定客户端发送消息(基于标识符)
  • 广播消息

更新:

> 添加

  • config.sendmessage以将消息发送到单个客户端

    我实施的授权方式是好的吗?!

    Main.java

    @SpringBootApplication
    public class Main {
    
        public static void main(final String[] args) {
            SpringApplication.run(Main.class, args);
        }
    
    }
    

    config.java

    @EnableIntegration
    @IntegrationComponentScan
    @Configuration
    public class Config implements ApplicationListener<TcpConnectionEvent> {
    
        private static final Logger LOGGER = Logger.getLogger(Config.class.getName());
    
        @Bean
        public AbstractServerConnectionFactory AbstractServerConnectionFactory() {
            return new TcpNetServerConnectionFactory(8181);
        }
    
        @Bean
        public TcpInboundGateway TcpInboundGateway(AbstractServerConnectionFactory connectionFactory) {
            TcpInboundGateway inGate = new TcpInboundGateway();
            inGate.setConnectionFactory(connectionFactory);
            inGate.setRequestChannel(getMessageChannel());
            return inGate;
        }
    
        @Bean
        public MessageChannel getMessageChannel() {
            return new DirectChannel();
        }
    
        @MessageEndpoint
        public class Echo {
    
            @Transformer(inputChannel = "getMessageChannel")
            public String convert(byte[] bytes) throws Exception {
                return new String(bytes);
            }
    
        }
    
        private static ConcurrentHashMap<String, TcpConnection> tcpConnections = new ConcurrentHashMap<>();
    
        @Override
        public void onApplicationEvent(TcpConnectionEvent tcpEvent) {
            TcpConnection source = (TcpConnection) tcpEvent.getSource();
            if (tcpEvent instanceof TcpConnectionOpenEvent) {
    
                LOGGER.info("Socket Opened " + source.getConnectionId());
                tcpConnections.put(tcpEvent.getConnectionId(), source);
    
                if (!authorizeIncomingConnection(source.getSocketInfo())) {
                    LOGGER.warn("Socket Rejected " + source.getConnectionId());
                    source.close();
                }
    
            } else if (tcpEvent instanceof TcpConnectionCloseEvent) {
                LOGGER.info("Socket Closed " + source.getConnectionId());
                tcpConnections.remove(source.getConnectionId());
            }
        }
    
        private boolean authorizeIncomingConnection(SocketInfo socketInfo) {
            //Authorization Logic , Like Ip,Mac Address WhiteList or anyThing else !
            return (System.currentTimeMillis() / 1000) % 2 == 0;
        }
    
        public static String broadCast(String message) {
            Set<String> connectionIds = tcpConnections.keySet();
            int successCounter = 0;
            int FailureCounter = 0;
            for (String connectionId : connectionIds) {
                try {
                    sendMessage(connectionId, message);
                    successCounter++;
                } catch (Exception e) {
                    FailureCounter++;
                }
            }
            return "BroadCast Result , Success : " + successCounter + " Failure : " + FailureCounter;
        }
    
        public static void sendMessage(String connectionId, final String message) throws Exception {
            tcpConnections.get(connectionId).send(new Message<String>() {
                @Override
                public String getPayload() {
                    return message;
                }
    
                @Override
                public MessageHeaders getHeaders() {
                    return null;
                }
            });
        }
    }
    
    @Controller
    public class MainController {
    
        @RequestMapping("/notify/{connectionId}/{message}")
        @ResponseBody
        public String home(@PathVariable String connectionId, @PathVariable String message) {
            try {
                Config.sendMessage(connectionId, message);
                return "Client Notified !";
            } catch (Exception e) {
                return "Failed To Notify Client , cause : \n " + e.toString();
            }
        }
    
    
        @RequestMapping("/broadCast/{message}")
        @ResponseBody
        public String home(@PathVariable String message) {
            return Config.broadCast(message);
        }
    
    }
    

    广播

    http://localhost:8080/broadcasty/{message}

  • 共有1个答案

    陈德泽
    2023-03-14

    TCPConnectionOpenEvent包含ConnectionID属性。来自该客户端的每个消息在ipheaders.connection_id消息头中将具有相同的属性。

    1. 添加一个自定义路由器,跟踪每个连接的登录状态。
    2. 查找连接id,如果未经过身份验证,则路由到质询/响应子流。
    3. 通过身份验证后,路由到正常流。

    要使用任意消息传递(而不是请求/响应),请使用TCPreceivingChannelAdapterTCPSendingMessageHandler而不是入站网关。两者配置为使用相同的连接工厂。对于发送到消息处理程序的每个消息,添加ipheaders.connection_id标头以针对特定客户机。

     类似资料:
    • 我遇到一些插座的问题。 我正在尝试使一个并发服务器接受多个客户端。 当客户端连接到服务器时,服务器会创建一个新线程并侦听套接字。然后,如果客户端发送某些内容,服务器必须读取它。 在客户端,我只需打开一个字典(txt格式),然后通过套接字发送。 在服务器上,我得到的唯一信息是: 无效的 服务器 客户 请忘记秋千组件。我觉得所有插座都没问题。为什么我在服务器端什么都得不到? 请帮忙 亲切的问候

    • RabbitMQ服务器中存在一种行为,即当达到水印值时,它将不接受后续连接/操作,直到重新平衡自身。RabbitMQ客户机在连接超时后发生这种情况时会优雅地获得超时,但我们使用的是Spring AMQP,它会继续挂起。 复制步骤 o创建RabbitMQ HA群集 o创建一个生成和使用消息的简单程序 a)使用Spring AMQP b)使用RabbitMQ客户端 o使RabbitMQ服务器在内存中达

    • 我正在编写一个类,用于创建对BigQuery和Google云存储的授权。 在过去,我曾使用,但已被弃用。我试图使用,但我发现它只允许我使用,而我需要。 我知道可以从转换为,但我不知道如何将它们转换成相反的方向(转换为)。例如,我像这样创建连接: 有人能给我指明如何实现这一目标的方向吗? 谢谢!

    • 我设法创建了基本的远程管理员工具,它运行良好,我使用了基本的tcp套接字和C++中的多线程。我可以用一些功能来远程使用它,这就像90%完成了,但我的软件没有任何东西可以检测客户端断开,除了当客户端手动关闭时,客户端会发送断开消息给服务器,但当用户拔掉网络插头或其他东西时,断开发生时,什么是最好的处理方法,我正在寻找一种专业的方法来做,比如如果客户端断开,服务器会立即检测到哪个客户端断开。

    • 我希望能够连接到需要智能卡的个人证书进行身份验证的https站点。我想我已经很接近让它工作了,但不知道如何克服这个例外: 由于合同关系,我不能共享我的代码,但这里有一个总结: 我创建了一个密钥库,其中包含从浏览器导出的所有证书。我使用此密钥存储作为SSLContext的信任存储。我非常肯定这个密钥库包含正确的CA证书来验证远程站点的证书,因为它修复了“无法找到请求目标的有效证书路径”的异常。 我可

    • 我试图用java实现一个客户端服务器,在这里我读取客户端中的输入并在服务器中执行UperCase,然后返回客户端并打印UperCase。我使用ObjectOutputStream和ObjectInputStream进行读写,但是当我在客户机中键入一个msg时,程序会显示以下错误: Digite uma msg casa java.io.eofexception位于java.io.datainput