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