SpringBoot之集成Socket
本文内容纲要:
1、Socket是什么,这里不做介绍。开发环境:jdk1.8,win7_64旗舰版,idea
2、初始化一个springboot项目
3、开始Socket服务端实现,Socket相关接口在java.net包中已经存在,所以这里不需要再做额外的引用
3.1、SocketServer,是Socket服务端核心
packagecom.geniuses.sewage_zero_straight.net.socket;
importcom.geniuses.sewage_zero_straight.bean.User;
importcom.geniuses.sewage_zero_straight.service.UserService;
importcom.geniuses.sewage_zero_straight.util.JSONUtil;
importlombok.Data;
importlombok.NoArgsConstructor;
importlombok.extern.slf4j.Slf4j;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.annotation.Value;
importorg.springframework.context.annotation.PropertySource;
importorg.springframework.stereotype.Component;
importjava.io.IOException;
importjava.net.ServerSocket;
importjava.net.Socket;
importjava.util.List;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Executors;
importstaticcom.geniuses.sewage_zero_straight.net.socket.SocketHandler.*;
@Slf4j
@Data
@Component
@PropertySource("classpath:socket.properties")
@NoArgsConstructor
publicclassSocketServer{
@Value("${port}")
privateIntegerport;
privatebooleanstarted;
privateServerSocketserverSocket;
privateExecutorServiceexecutorService=Executors.newCachedThreadPool();
publicstaticvoidmain(String[]args){
newSocketServer().start(8068);
}
publicvoidstart(){
start(null);
}
@Autowired
privateUserServiceuserService;//测试使用
publicvoidstart(Integerport){
log.info("port:{},{}",this.port,port);
try{
serverSocket=newServerSocket(port==null?this.port:port);
started=true;
log.info("Socket服务已启动,占用端口:{}",serverSocket.getLocalPort());
}catch(IOExceptione){
log.error("端口冲突,异常信息:{}",e);
System.exit(0);
}
while(started){
try{
Socketsocket=serverSocket.accept();
socket.setKeepAlive(true);
ClientSocketregister=register(socket);
log.info("客户端已连接,其Key值为:{}",register.getKey());
List<User>list=userService.queryEntityListAll();
SocketHandler.sendMessage(register,JSONUtil.toJson(list));
if(register!=null){
executorService.submit(register);
}
}catch(IOExceptione){
e.printStackTrace();
}
}
}
}
3.2、SocketPool是Socket连接的池,存放着所有已连接的socket对象,ClientSocket是自定义的一个客户端Socket类
packagecom.geniuses.sewage_zero_straight.net.socket;
importjava.util.concurrent.ConcurrentHashMap;
publicclassSocketPool{
privatestaticfinalConcurrentHashMap<String,ClientSocket>ONLINE_SOCKET_MAP=newConcurrentHashMap<>();
publicstaticvoidadd(ClientSocketclientSocket){
if(clientSocket!=null&&!clientSocket.getKey().isEmpty())
ONLINE_SOCKET_MAP.put(clientSocket.getKey(),clientSocket);
}
publicstaticvoidremove(Stringkey){
if(!key.isEmpty())
ONLINE_SOCKET_MAP.remove(key);
}
}
3.3、ClientSocket
packagecom.geniuses.sewage_zero_straight.net.socket;
importcom.geniuses.sewage_zero_straight.bean.LZP_DATASERVER_TC_PROHIBSOURCE;
importcom.geniuses.sewage_zero_straight.service.LZP_DATASERVER_TC_PROHIBSOURCEService;
importlombok.Data;
importlombok.extern.slf4j.Slf4j;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Component;
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.net.Socket;
importjava.util.concurrent.TimeUnit;
importstaticcom.geniuses.sewage_zero_straight.net.socket.SocketHandler.*;
/**
*@authorzhoujian
*自定义封装的连接的客户端
*/
@Slf4j
@Data
publicclassClientSocketimplementsRunnable{
privateSocketsocket;
privateDataInputStreaminputStream;
privateDataOutputStreamoutputStream;
privateStringkey;
privateStringmessage;
@Override
publicvoidrun(){
//每5秒进行一次客户端连接,判断是否需要释放资源
while(true){
try{
TimeUnit.SECONDS.sleep(5);
}catch(InterruptedExceptione){
e.printStackTrace();
}
if(isSocketClosed(this)){
log.info("客户端已关闭,其Key值为:{}",this.getKey());
//关闭对应的服务端资源
close(this);
break;
}
}
}
}
3.4、SocketHandler,Socket操作处理类
packagecom.geniuses.sewage_zero_straight.net.socket;
importlombok.extern.slf4j.Slf4j;
importjava.io.DataInputStream;
importjava.io.DataOutputStream;
importjava.io.IOException;
importjava.net.Socket;
importstaticcom.geniuses.sewage_zero_straight.net.socket.SocketPool.*;
/**
*Socket操作处理类
*/
@Slf4j
publicclassSocketHandler{
/**
*将连接的Socket注册到Socket池中
*@paramsocket
*@return
*/
publicstaticClientSocketregister(Socketsocket){
ClientSocketclientSocket=newClientSocket();
clientSocket.setSocket(socket);
try{
clientSocket.setInputStream(newDataInputStream(socket.getInputStream()));
clientSocket.setOutputStream(newDataOutputStream(socket.getOutputStream()));
byte[]bytes=newbyte[1024];
clientSocket.getInputStream().read(bytes);
clientSocket.setKey(newString(bytes,"utf-8"));
add(clientSocket);
returnclientSocket;
}catch(IOExceptione){
e.printStackTrace();
}
returnnull;
}
/**
*向指定客户端发送信息
*@paramclientSocket
*@parammessage
*/
publicstaticvoidsendMessage(ClientSocketclientSocket,Stringmessage){
try{
clientSocket.getOutputStream().write(message.getBytes("utf-8"));
//clientSocket.getOutputStream().writeUTF(message);
}catch(IOExceptione){
log.error("发送信息异常:{}",e);
close(clientSocket);
}
}
/**
*获取指定客户端的上传信息
*@paramclientSocket
*@return
*/
publicstaticStringonMessage(ClientSocketclientSocket){
byte[]bytes=newbyte[1024];
try{
clientSocket.getInputStream().read(bytes);
Stringmsg=newString(bytes,"utf-8");
returnmsg;
}catch(IOExceptione){
e.printStackTrace();
close(clientSocket);
}
returnnull;
}
/**
*指定Socket资源回收
*@paramclientSocket
*/
publicstaticvoidclose(ClientSocketclientSocket){
log.info("进行资源回收");
if(clientSocket!=null){
log.info("开始回收socket相关资源,其Key为{}",clientSocket.getKey());
remove(clientSocket.getKey());
Socketsocket=clientSocket.getSocket();
try{
socket.shutdownInput();
socket.shutdownOutput();
}catch(IOExceptione){
log.error("关闭输入输出流异常,{}",e);
}finally{
try{
socket.close();
}catch(IOExceptione){
log.error("关闭socket异常{}",e);
}
}
}
}
/**
*发送数据包,判断数据连接状态
*@paramclientSocket
*@return
*/
publicstaticbooleanisSocketClosed(ClientSocketclientSocket){
try{
clientSocket.getSocket().sendUrgentData(1);
returnfalse;
}catch(IOExceptione){
returntrue;
}
}
}
4、模拟客户端
packagecom.geniuses.sewage_zero_straight.net.socket;
importlombok.extern.slf4j.Slf4j;
importjava.io.*;
importjava.net.Socket;
importjava.util.UUID;
@Slf4j
publicclassChatClient{
publicstaticvoidmain(String[]args)throwsIOException{
Stringhost="192.168.2.156";
intport=8068;
//与服务端建立连接
Socketsocket=newSocket(host,port);
socket.setOOBInline(true);
//建立连接后获取输出流
DataOutputStreamoutputStream=newDataOutputStream(socket.getOutputStream());
DataInputStreaminputStream=newDataInputStream(socket.getInputStream());
Stringuuid=UUID.randomUUID().toString();
log.info("uuid:{}",uuid);
outputStream.write(uuid.getBytes());
DataInputStreaminputStream1=newDataInputStream(socket.getInputStream());
Stringcontent="";
while(true){
byte[]buff=newbyte[1024];
inputStream.read(buff);
Stringbuffer=newString(buff,"utf-8");
content+=buffer;
log.info("info:{}",buff);
Filefile=newFile("json.json");
FileWriterfileWriter=newFileWriter(file);
fileWriter.write(content);
fileWriter.flush();
}
}
}
5、Socket配置,这样,在启动SpringBoot应用的时候,就会将Socket服务也一并启动(此处有坑,也就是启动方式的问题,使用内置的tomcat启动是可以这样操作的,如果打包为war包在外置的tomcat进行启动,那么这里的设置是无效的,如何操作:)
packagecom.geniuses.sewage_zero_straight;
importcom.geniuses.sewage_zero_straight.net.socket.SocketServer;
importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;
importorg.springframework.context.ApplicationContext;
@SpringBootApplication
publicclassSocketApplication{
publicstaticvoidmain(String[]args){
ApplicationContextapplicationContext=SpringApplication.run(SocketApplication.class,args);
applicationContext.getBean(SocketServer.class).start();//在spring容器启动后,取到已经初始化的SocketServer,启动Socket服务
}
}
6、这里只是简单的Socket实现,更多...
本文内容总结:
原文链接:https://www.cnblogs.com/threadj/p/10553048.html