SpringBoot整合socket通信
SpringBoot整合socket通信
一、介绍
很多人都不太理解socket
通信指的是什么,简单来讲,它是一个完成两个应用程序之间的数据传输的东西。
socket
是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象,一个socket
就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,socket
上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口。
本次使用Java
语言去实现socket
通信,用的SpringBoot
框架,当然直接使用main
方法启用也是没有问题的。
推荐访问:个人博客
二、实现
1)服务端
先设置一下需要用到的配置,主要就是这个端口号,我觉得放配置文件中会比较好
socket-port:
testSocket: 2333
socket
服务端启动类
此处使用到了bean
的初始化,如果不熟悉的话,使用静态代码块也是一样的
package com.banmoon.test.socket;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component("testSocket")
public class TestSocketStart {
@Value("${socket-port.testSocket}")
private Integer port;
public static ServerSocket testSocket = null;
private static final ThreadPoolExecutor testSocketThreadPool = new ThreadPoolExecutor(15, 15,
10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
@PostConstruct
public void start() {
new Thread(() -> {
try {
testSocket = new ServerSocket(port);
log.info("socket服务端开启");
while (true){
Socket socket = testSocket.accept();
testSocketThreadPool.execute(new TestSocketService(socket));
}
} catch (IOException e) {
log.info("socket服务启动异常");
e.printStackTrace();
}
}, "testSocket").start();
}
}
具体socket
服务类,此类用来处理业务消息,同时这个一个多线程类
package com.banmoon.test.socket;
import cn.hutool.json.JSONObject;
import com.banmoon.test.dto.ResultData;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
@Slf4j
@AllArgsConstructor
public class TestSocketService implements Runnable{
private Socket socket;
@Override
@SneakyThrows
public void run() {
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
try {
// 输入流接收数据
ois = new ObjectInputStream(socket.getInputStream());
// 输出流发送数据
oos = new ObjectOutputStream(socket.getOutputStream());
JSONObject jsonObject = (JSONObject) ois.readObject();
log.info("模拟处理业务:{}", jsonObject);
// 输出流发送返回参数
JSONObject resultJson = new JSONObject(ResultData.success());
oos.writeUTF(resultJson.toString());
oos.flush();
} catch (Exception e) {
log.info("接收数据异常socket关闭");
e.printStackTrace();
} finally {
// 关闭流
oos.close();
ois.close();
socket.close();
log.info("关闭流成功" + System.lineSeparator());
}
}
}
服务端编写完毕,剩下就是在客户端了,我们该如何调用?
2)客户端
客户端这边的类,实现了一个Callable
接口,使其变成一个有返回值的多线程类。
package com.banmoon.test;
import cn.hutool.json.JSONObject;
import lombok.AllArgsConstructor;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.concurrent.Callable;
@AllArgsConstructor
public class TestSocketClientService implements Callable<String> {
private JSONObject paramJson;
@Override
public String call() throws Exception {
Socket socket = null;
ObjectInputStream ois = null;
ObjectOutputStream oos = null;
try {
socket = new Socket("127.0.0.1", 2333);
// 输出流写数据
oos = new ObjectOutputStream(socket.getOutputStream());
// 输入流读数据
ois = new ObjectInputStream(socket.getInputStream());
// 输出流给服务端发送数据
oos.writeObject(paramJson);
oos.flush();
// 输入流接收服务端返回的数据
String message = ois.readUTF();
return message;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
ois.close();
oos.close();
socket.close();
}
}
}
当然,此处写的比较简陋,注意客户端和服务端发送、读取信息时需要相同的编码。
3)测试
服务端,客户端都有了,我们该如何发起通信?
首先,我们先启用SpringBoot
服务端,启动完成后再对客户端进行使用
如下,我们只需要创建线程,把paramJson
传入,启用这个线程,就能够发送数据了。
package com.banmoon.test;
import cn.hutool.json.JSONObject;
import com.banmoon.test.dto.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.util.concurrent.*;
@Slf4j
public class SomethingTest {
@Test
public void test() throws InterruptedException, ExecutionException {
ExecutorService service = Executors.newFixedThreadPool(1);
for (int i = 0; i < 5; i++) {
JSONObject paramJson = new JSONObject(new UserDTO("半月无霜", "男", 18+i));
Future<String> future = service.submit(new TestSocketClientService(paramJson));
log.info("服务端返回的参数:{}", future.get());
TimeUnit.SECONDS.sleep(2);
}
service.shutdown();
}
}
三、最后
我知道,这一次挺水的,我自己都没有搞明白socket
通信到底是个啥!!!
先这样记录一下吧,后续要去看网络通信的书了,沉淀是对自己最好的投资。
我是半月,祝你幸福!!!
入我相思门,知我相思苦,
长相思兮长相忆,短相思兮无穷极,
早知如此绊人心,何如当初莫相识。