[英]spring tcp socket , authorizing clients and handle pending response
The Spring framework support tcp connection as well , i wrote code below to setup a simple socket server , i am confused about adding below futures to my socket server : Spring框架也支持tcp连接,我编写下面的代码来设置一个简单的套接字服务器,我很困惑将下面的期货添加到我的套接字服务器:
UPDATE : 更新:
Config.sendMessage
added to send message to single client 添加Config.sendMessage
以向单个客户端发送消息
Config.broadCast
added to broadcast message Config.broadCast
添加到广播消息
authorizeIncomingConnection
to authorize clients , accept or reject connections authorizeIncomingConnection
授权客户端,接受或拒绝连接
tcpConnections
static filed added to keep tcpEvent sources 添加tcpConnections
静态字段以保留tcpEvent源
Questions ! 问题!
is using tcpConnections
HashMap good idea ?! 使用tcpConnections
HashMap好主意?!
is the authorization method i implemented a good one ?! 是我实施好的授权方法吗?
Main.java Main.java
@SpringBootApplication
public class Main {
public static void main(final String[] args) {
SpringApplication.run(Main.class, args);
}
}
Config.java 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;
}
});
}
}
MainController.java MainController.java
@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);
}
}
Usage : 用法:
notify single client 通知单个客户端
http://localhost:8080/notify/{connectionId}/{message}
broadCast 广播
http://localhost:8080/broadCast/{message}
The TcpConnectionOpenEvent
contains a connectionId
property. TcpConnectionOpenEvent
包含connectionId
属性。 Each message coming from that client will have the same property in the IpHeaders.CONNECTION_ID
message header. 来自该客户端的IpHeaders.CONNECTION_ID
消息在IpHeaders.CONNECTION_ID
消息头中都具有相同的属性。
To use arbitrary messaging (rather than request/response) use a TcpReceivingChannelAdapter
and TcpSendingMessageHandler
instead of an inbound gateway. 要使用任意消息传递(而不是请求/响应),请使用TcpReceivingChannelAdapter
和TcpSendingMessageHandler
而不是入站网关。 Both configured to use the same connection factory. 两者都配置为使用相同的连接工厂。 For each message sent to the message handler, add the IpHeaders.CONNECTION_ID
header to target the specific client. 对于发送到消息处理程序的每条消息,添加IpHeaders.CONNECTION_ID
标头以定位特定客户端。
To broadcast, send a message for each connection id. 要广播,请为每个连接ID发送消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.