1、Socket是什么,这里不做介绍。开发环境:jdk1.8,win7_64旗舰版,idea
 
2、初始化一个springboot项目
 
3、开始Socket服务端实现,Socket相关接口在java.net包中已经存在,所以这里不需要再做额外的引用
    3.1、SocketServer,是Socket服务端核心
package com.geniuses.sewage_zero_straight.net.socket;

import com.geniuses.sewage_zero_straight.bean.User;
import com.geniuses.sewage_zero_straight.service.UserService;
import com.geniuses.sewage_zero_straight.util.JSONUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component; import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static com.geniuses.sewage_zero_straight.net.socket.SocketHandler.*; @Slf4j
@Data
@Component
@PropertySource("classpath:socket.properties")
@NoArgsConstructor
public class SocketServer { @Value("${port}")
private Integer port;
private boolean started;
private ServerSocket serverSocket;
private ExecutorService executorService = Executors.newCachedThreadPool(); public static void main(String[] args){
new SocketServer().start(8068);
} public void start(){
start(null);
}
@Autowired
private UserService userService;//测试使用 public void start(Integer port){
log.info("port: {}, {}", this.port, port);
try {
serverSocket = new ServerSocket(port == null ? this.port : port);
started = true;
log.info("Socket服务已启动,占用端口: {}", serverSocket.getLocalPort());
} catch (IOException e) {
log.error("端口冲突,异常信息:{}", e);
System.exit(0);
} while (started){
try {
Socket socket = serverSocket.accept();
socket.setKeepAlive(true);
ClientSocket register = 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 (IOException e) {
e.printStackTrace();
}
}
}
}

3.2、SocketPool是Socket连接的池,存放着所有已连接的socket对象,ClientSocket是自定义的一个客户端Socket类

package com.geniuses.sewage_zero_straight.net.socket;

import java.util.concurrent.ConcurrentHashMap;

public class SocketPool {

    private static final ConcurrentHashMap<String, ClientSocket> ONLINE_SOCKET_MAP = new ConcurrentHashMap<>();

    public static void add(ClientSocket clientSocket){
if (clientSocket != null && !clientSocket.getKey().isEmpty())
ONLINE_SOCKET_MAP.put(clientSocket.getKey(), clientSocket);
} public static void remove(String key){
if (!key.isEmpty())
ONLINE_SOCKET_MAP.remove(key);
}
}

3.3、ClientSocket

package com.geniuses.sewage_zero_straight.net.socket;

import com.geniuses.sewage_zero_straight.bean.LZP_DATASERVER_TC_PROHIBSOURCE;
import com.geniuses.sewage_zero_straight.service.LZP_DATASERVER_TC_PROHIBSOURCEService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.concurrent.TimeUnit; import static com.geniuses.sewage_zero_straight.net.socket.SocketHandler.*; /**
* @author zhoujian
* 自定义封装的连接的客户端
*/
@Slf4j
@Data
public class ClientSocket implements Runnable{ private Socket socket;
private DataInputStream inputStream;
private DataOutputStream outputStream;
private String key;
private String message; @Override
public void run() {
//每5秒进行一次客户端连接,判断是否需要释放资源
while (true){
try {
TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) {
e.printStackTrace();
}
if (isSocketClosed(this)){
log.info("客户端已关闭,其Key值为:{}", this.getKey());
//关闭对应的服务端资源
close(this);
break;
}
}
}
}

3.4、SocketHandler,Socket操作处理类

package com.geniuses.sewage_zero_straight.net.socket;

import lombok.extern.slf4j.Slf4j;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket; import static com.geniuses.sewage_zero_straight.net.socket.SocketPool.*; /**
* Socket操作处理类
*/
@Slf4j
public class SocketHandler{ /**
* 将连接的Socket注册到Socket池中
* @param socket
* @return
*/
public static ClientSocket register(Socket socket){
ClientSocket clientSocket = new ClientSocket();
clientSocket.setSocket(socket);
try {
clientSocket.setInputStream(new DataInputStream(socket.getInputStream()));
clientSocket.setOutputStream(new DataOutputStream(socket.getOutputStream()));
byte[] bytes = new byte[1024];
clientSocket.getInputStream().read(bytes);
clientSocket.setKey(new String(bytes, "utf-8"));
add(clientSocket);
return clientSocket;
} catch (IOException e) {
e.printStackTrace();
}
return null;
} /**
* 向指定客户端发送信息
* @param clientSocket
* @param message
*/
public static void sendMessage(ClientSocket clientSocket, String message){
try {
clientSocket.getOutputStream().write(message.getBytes("utf-8"));
//clientSocket.getOutputStream().writeUTF(message);
} catch (IOException e) {
log.error("发送信息异常:{}", e);
close(clientSocket);
}
} /**
* 获取指定客户端的上传信息
* @param clientSocket
* @return
*/
public static String onMessage(ClientSocket clientSocket){
byte[] bytes = new byte[1024];
try {
clientSocket.getInputStream().read(bytes);
String msg = new String(bytes, "utf-8");
return msg;
} catch (IOException e) {
e.printStackTrace();
close(clientSocket);
}
return null;
} /**
* 指定Socket资源回收
* @param clientSocket
*/
public static void close(ClientSocket clientSocket){
log.info("进行资源回收");
if (clientSocket != null){
log.info("开始回收socket相关资源,其Key为{}", clientSocket.getKey());
remove(clientSocket.getKey());
Socket socket = clientSocket.getSocket();
try {
socket.shutdownInput();
socket.shutdownOutput();
} catch (IOException e) {
log.error("关闭输入输出流异常,{}", e);
}finally {
try {
socket.close();
} catch (IOException e) {
log.error("关闭socket异常{}", e);
}
}
}
} /**
* 发送数据包,判断数据连接状态
* @param clientSocket
* @return
*/
public static boolean isSocketClosed(ClientSocket clientSocket){
try {
clientSocket.getSocket().sendUrgentData(1);
return false;
} catch (IOException e) {
return true;
}
} }

4、模拟客户端

package com.geniuses.sewage_zero_straight.net.socket;

import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.net.Socket;
import java.util.UUID; @Slf4j
public class ChatClient { public static void main(String[] args) throws IOException {
String host = "192.168.2.156";
int port = 8068; //与服务端建立连接
Socket socket = new Socket(host, port);
socket.setOOBInline(true); //建立连接后获取输出流
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
String uuid = UUID.randomUUID().toString();
log.info("uuid: {}", uuid);
outputStream.write(uuid.getBytes());
DataInputStream inputStream1 = new DataInputStream(socket.getInputStream());
String content = "";
while (true){
byte[] buff = new byte[1024];
inputStream.read(buff);
String buffer = new String(buff, "utf-8");
content += buffer;
log.info("info: {}", buff);
File file = new File("json.json");
FileWriter fileWriter = new FileWriter(file);
fileWriter.write(content);
fileWriter.flush();
}
}
}

5、Socket配置,这样,在启动SpringBoot应用的时候,就会将Socket服务也一并启动(此处有坑,也就是启动方式的问题,使用内置的tomcat启动是可以这样操作的,如果打包为war包在外置的tomcat进行启动,那么这里的设置是无效的,如何操作:)

package com.geniuses.sewage_zero_straight;

import com.geniuses.sewage_zero_straight.net.socket.SocketServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext; @SpringBootApplication
public class SocketApplication{ public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(SocketApplication.class, args);
applicationContext.getBean(SocketServer.class).start();//在spring容器启动后,取到已经初始化的SocketServer,启动Socket服务
} }

6、这里只是简单的Socket实现,更多...

SpringBoot之集成Socket的更多相关文章

  1. springboot elasticsearch 集成注意事项

    文章来源: http://www.cnblogs.com/guozp/p/8686904.html 一 elasticsearch基础 这里假设各位已经简单了解过elasticsearch,并不对es ...

  2. Springboot Application 集成 OSGI 框架开发

    内容来源:https://www.ibm.com/developerworks/cn/java/j-springboot-application-integrated-osgi-framework-d ...

  3. SpringBoot项目集成Hystrix

    Hystrix Hystrix是由Netflix开源的一个服务隔离组件,通过服务隔离来避免由于依赖延迟.异常,引起资源耗尽导致系统不可用的解决方案. 1.什么是服务熔断   服务熔断就是对该服务的调用 ...

  4. 钉钉通知机器人与SpringBoot的集成

    Spring Boot Admin 集成自定义监控告警(2.0.1版本)------钉钉机器人 - yuancao24的博客 - CSDN博客https://blog.csdn.net/yuancao ...

  5. SpringBoot项目集成PageHelper使用

    SpringBoot项目集成PageHelper使用 一.开始 ​ 地址:https://github.com/pagehelper/Mybatis-PageHelper ​ 在spring boot ...

  6. Springboot简单集成ActiveMQ

    Springboot简单集成ActiveMQ 消息发送者的实现 pom.xml添加依赖 <dependency> <groupId>org.springframework.bo ...

  7. 在springboot中集成mybatis开发

    在springboot中利用mybatis框架进行开发需要集成mybatis才能进行开发,那么如何在springboot中集成mybatis呢?按照以下几个步骤就可以实现springboot集成myb ...

  8. 在springboot中集成jsp开发

    springboot就是一个升级版的spring.它可以极大的简化xml配置文件,可以采用全注解形式开发,一个字就是很牛.在springboot想要使用jsp开发,需要集成jsp,在springboo ...

  9. Swagger详解(SpringBoot+Swagger集成)(转)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/ai_miracle/article/de ...

随机推荐

  1. springMVC访问 WEB-INF 下的 jsp 和 html

    配置freemarker,记得加上jar包 <?xml version="1.0" encoding="UTF-8"?> <beans xml ...

  2. POJ--3321 Apple Tree(树状数组+dfs(序列))

    Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 22613 Accepted: 6875 Descripti ...

  3. poj3261 Milk Patterns【后缀数组】【二分】

    Farmer John has noticed that the quality of milk given by his cows varies from day to day. On furthe ...

  4. UVA 11776 - Oh Your Royal Greediness! - [贪心/模拟]

    题目链接:https://cn.vjudge.net/problem/UVA-11776 题意: 给出数字n(0<=n<=1000),代表有n个农民,接下来有n行,每行两个数字S和E代表这 ...

  5. POJ 1849 - Two - [DFS][树形DP]

    Time Limit: 1000MS Memory Limit: 30000K Description The city consists of intersections and streets t ...

  6. Java不定参数

    先看两个简单的例子,来感受一下Java的不定长度参数 第一个例子: public class VariArgs { public static void main(String[] args) { t ...

  7. 【Loadrunner】Loadrunner Vuser 两种运行方式【error:not enough memory解决方案】

    Loadrunner Vuser 两种运行方式 报错如下解决方案: 报错原因:都消息内存,之前用户是按线程跑,一个进程开了多个线程,其中有部分内存是这些线程共享的,出错应该是内存出现冲突了不够用了.现 ...

  8. 在linux下使用sqlcmd

    1.curl https://packages.microsoft.com/config/rhel/6/prod.repo > /etc/yum.repos.d/mssql-release.re ...

  9. redis 在windows 上面的安装和使用,集群搭建

    redis作为nosql数据库,将数据存储到内存中(缓存),具有非常高的性能.下面讲解一下redis的安装及java api的使用. 1:redis 安装 windows 上面直接下载msi文件,安装 ...

  10. 畅通工程续 (SPFA模板Floy模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=1874 SPFA #include <iostream> #include <stdio.h&g ...