服务端配置SocketIo与客户端实现通信
业务需求:Android设备 与后端 实现实时信息通讯,服务器推送实时信息到Android设备
技术选型:springBoot netty-Socketio
netty-Socketio
netty-socketio 是基于netty的java版的即时消息推送项目。通过netty-socketio ,我们可以轻松的实现服务端主动向客户端推送消息的场景,例如:股票价格变动、k线图、消息提醒等。它和webSocket有相同的作用,只不过netty-socketio可以支持所有的浏览器。
首先在yml文件中配置socketIo参数
socketIo:
win: 0.0.0.0
linxu: 0.0.0.0
port: 9090
maxFramePayloadLength: 1048576
maxHttpContentLength: 1048576
allowCustomRequests: true
upgradeTimeout: 10000
pingTimeout: 60000
pingInterval: 25000
添加NettySocketConfig文件
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;
import com.firstdream.customer.util.YmlUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class NettySocketConfig {
private String ipWin;
private String ipLinxu;
private int port;
private int maxFramePayloadLength;
private int maxHttpContentLength;
private boolean allowCustomRequests;
private int upgradeTimeout;
private int pingTimeout;
private int pingInterval;
@Bean
public SocketIOServer socketIOServer() throws Exception{
ipWin = (String) YmlUtil.getValue("socketIo.win");
ipLinxu = (String)YmlUtil.getValue("socketIo.linxu");
port = (Integer) YmlUtil.getValue("socketIo.port");
maxFramePayloadLength=(Integer) YmlUtil.getValue("socketIo.maxFramePayloadLength");
maxHttpContentLength=(Integer) YmlUtil.getValue("socketIo.maxHttpContentLength");
allowCustomRequests=(Boolean) YmlUtil.getValue("socketIo.allowCustomRequests");
upgradeTimeout=(Integer) YmlUtil.getValue("socketIo.upgradeTimeout");
pingTimeout=(Integer) YmlUtil.getValue("socketIo.pingTimeout");
pingInterval=(Integer) YmlUtil.getValue("socketIo.pingInterval");
com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();
String os = System.getProperty("os.name");
if(os.toLowerCase().startsWith("win")){
//在本地window环境测试时用localhost
config.setHostname(ipWin);
} else {
//部署到你的远程服务器正式发布环境时用服务器公网ip
config.setHostname(ipLinxu);
}
// 端口,任意
config.setPort(port);
config.setMaxFramePayloadLength(maxFramePayloadLength);
config.setMaxHttpContentLength(maxHttpContentLength);
config.setAllowCustomRequests(allowCustomRequests);
config.setUpgradeTimeout(upgradeTimeout);
config.setPingTimeout(pingTimeout);
config.setPingInterval(pingInterval);
//该处进行身份验证h
config.setAuthorizationListener(handshakeData -> {
//http://localhost:8081?username=test&password=test
//例如果使用上面的链接进行connect,可以使用如下代码获取用户密码信息
//String username = data.getSingleUrlParam("username");
//String password = data.getSingleUrlParam("password");
return true;
});
final SocketIOServer server = new SocketIOServer(config);
return server;
}
@Bean
public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
return new SpringAnnotationScanner(socketServer);
}
}
配置SocketIoServerMapUtil,进行socketIo连接缓存
import com.corundumstudio.socketio.SocketIOClient;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class SocketIoServerMapUtil {
public static ConcurrentMap<String, SocketIOClient> webSocketMap = new ConcurrentHashMap<>();
public static void put(String key, SocketIOClient SocketIOClient) {
webSocketMap.put(key, SocketIOClient);
}
public static SocketIOClient get(String key) {
return webSocketMap.get(key);
}
public static void remove(String key) {
webSocketMap.remove(key);
}
public static Collection<SocketIOClient> getValues() {
return webSocketMap.values();
}
public static ConcurrentMap<String, SocketIOClient> getWebSocketMap() {
return webSocketMap;
}
}
添加socketIoServer用来处理服务器与安卓设备进行交互
@Component
public class SocketIoServer {
public static SocketIOServer socketIoServer;
@Autowired
public SocketIoServer(SocketIOServer server) {
this.socketIoServer = server;
}
@OnConnect
public void onConnect(SocketIOClient client) {
String sa = client.getRemoteAddress().toString();
String clientIp = sa.substring(1, sa.indexOf(":"));// 获取设备ip
Map<String, List<String>> params = client.getHandshakeData().getUrlParams();
System.out.println(clientIp + "------------clientIsOnline-------------" );
SocketIoServerMapUtil.put(clientIp, client);
}
@OnDisconnect
public void onDisconnect(SocketIOClient client) {
String sa = client.getRemoteAddress().toString();
String clientIp = sa.substring(1, sa.indexOf(":"));// 获取设备ip
SocketIoServerMapUtil.remove(clientIp);
System.out.println(clientIp + "------------clientIsOffline-------------" );
}
@OnEvent(value = "login")
public void onEvent(SocketIOClient client, AckRequest ackRequest, JSONObject data) {
// 客户端推送advert_info事件时,onData接受数据,这里是string类型的json数据,还可以为Byte[],object其他类型
String sa = client.getRemoteAddress().toString();
String clientIp = sa.substring(1, sa.indexOf(":"));// 获取客户端连接的ip
Map<String, List<String>> params = client.getHandshakeData().getUrlParams();// 获取客户端url参数
System.out.println(clientIp + ":client:************" + data);
//进行一些业务逻辑处理
}
}
至此,服务器与安卓设备的socket交互就完成了