文章目录
一、TCP请求链路
①TCP客户端连接nginx8667端口,发送消息
②Nginx监听8667端口,反向代理携带请求参数访问TCP服务端
③TCP服务端接收TCP客户端请求后,经过业务逻辑,返回处理结果
④nginx将TCP服务端返回的结果响应给TCP客户端
二、实战
2.1. 暴露服务端口
TCP服务端先启动完成,腾讯云管控台暴露TCP 1004端口
2.2. nginx反向代理tcp
nginx演示版本1.22.0
nginx配置tcp反向代理配置
stream {
server {
listen 8667;
proxy_pass tcp服务端IP:tpc服务端端口;
# proxy_pass 101.xxx.xxx.80:10004;
}
}
完整配置见文章底部附录
2.3. tcp服务端
package com.gblfy.socketclent;// 服务上不要有包名,本地测试可以有包名
import com.alibaba.fastjson.JSON;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
/**
* tcp 服务端案例
*
* @author gblfy
* @date 2023-08-03
*/
public class SocketService {
public static void main(String[] args) throws IOException {
// 此端口为服务端暴露的端口自定义,客户端连接时需要连接词端口
ServerSocket ss = new ServerSocket(10004);
Socket socket = ss.accept();
String ip = socket.getInetAddress().getHostAddress();
System.out.println("客户端的ip地址为," + ip);
//1、获取Socket读取流
BufferedReader bufin = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
HashMap<Object, Object> map = new HashMap<>();
map.put("msg", "success");
map.put("status", 200);
//2、获取Socket输出流
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
String line = null;
while ((line = bufin.readLine()) != null) {
System.out.println(line);
// 3.服务端返回客户端消息
out.println("服务端返回的-->" + JSON.toJSONString(map));
// out.println("服务端返回的-->" + line.toUpperCase());
}
// 关闭连接
socket.close();
ss.close();
}
}
2.4. TCP客户端
package com.gblfy.socketclent;// 不要有包名
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
/**
* tcp 服务端案例
*
* @author gblfy
* @date 2023-08-03
*/
public class SocketClient8667 {
public static void main(String[] args) throws IOException {
//1、创建客户端Socket host 服务端IP地址 port 服务端端口
Socket socket = new Socket("127.0.0.1", 10004);
//2、获取终端输入的数据
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
//3、向服务端发送数据
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
// socket输入流,读取服务器返回的大写字母fias
BufferedReader bufin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = buf.readLine()) != null) {
// TODO 特殊场景 接收到某一个字符时,停止提供服务
// if ("over".equals(line)) {
// break;
// }
out.println(line);
//读取服务端大写的一行
String upperStr = bufin.readLine();
System.out.println(upperStr);
}
socket.close();
}
}
2.5. linux编译测试
建议找2台云服务器,演示采用腾讯云服务器
依次编译运行tcp 服务端代码、tcp 客户端代码
编译栗子:
javac tcp服务端.java
javac tcp客户端.java
运行栗子:
java tcp服务端
java tcp客户端
三、内部使用
3.1. 服务端案例
package com.gblfy.socketclent;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
@SpringBootApplication
public class SocketServiceApplication {
public static void main(String[] args) throws IOException {
SpringApplication.run(SocketServiceApplication.class, args);
ServerSocket serverSocket = new ServerSocket(10004);
while (true) {
Socket socket = serverSocket.accept();
new Thread(new ServerListener(socket)).start();
System.out.println("启动TCP服务器....");
}
}
}
- 十六进制报文
package com.gblfy.socketclent;
import com.alibaba.fastjson.JSON;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;
/**
* TCP 监听类接收客户端数据
*
* @author gblfy
* @date 2023-08-04
*/
public class ServerListener implements Runnable {
private Socket socket;
ServerListener(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
String ip = socket.getInetAddress().getHostAddress();
System.out.println("客户端的ip地址为," + ip);
//1、获取Socket读取流
BufferedReader bufin = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
//2、获取Socket输出流
HashMap<Object, Object> map = new HashMap<>();
map.put("msg", "success");
map.put("status", 200);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
String line = null;
while ((line = bufin.readLine()) != null) {
// 单独处理逻辑类
HandleService handleService = new HandleService();
handleService.handle(line);
// 3.TCP服务端返回消息
out.println("服务端返回的-->" + JSON.toJSONString(map));
}
System.out.println("----------------" + line);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.gblfy.socketclent;
import org.springframework.stereotype.Service;
/**
* TCP 服务端逻辑处理类
*
* @author gblfy
* @Date 2023-08-03
**/
@Service
public class HandleService {
public void handle(String msg) {
//TODO 解析数据 落库
System.out.println("------------" + msg);
}
}
3.2. 服务端(十六进制)
- 十六进制报文
package com.gblfy.socketclent;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
@SpringBootApplication
public class SocketServiceApplication {
public static void main(String[] args) throws IOException {
SpringApplication.run(SocketServiceApplication.class, args);
ServerSocket serverSocket = new ServerSocket(10004);
while (true) {
Socket socket = serverSocket.accept();
new Thread(new ServerListener(socket)).start();
System.out.println("启动TCP服务器....");
}
}
}
package com.gblfy.socketclent;
import com.alibaba.fastjson.JSON;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.HashMap;
/**
* TCP Server 监听类接收客户端(飞机机载设备)数据发送的十六进制数据
*
* @author gblfy
* @date 2023-08-04
*/
public class ServerListener implements Runnable {
private Socket socket;
ServerListener(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
String ip = socket.getInetAddress().getHostAddress();
System.out.println("客户端的ip地址为," + ip);
//1、获取Socket读取流
BufferedReader bufin = null;
bufin = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
//2、获取Socket输出流
HashMap<Object, Object> map = new HashMap<>();
map.put("msg", "success");
map.put("status", 200);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
StringBuilder asciiOutput = new StringBuilder();
System.out.println("开始返回");
int line ;
char[] cbuf = new char[1024];
while ((line = bufin.read(cbuf)) != -1) {
String str = new String(cbuf, 0, line);
for (int i = 0; i < str.length(); i += 2) {
// System.out.println("====接收原始消息====="+line);
String hexByte = str.substring(i, i + 2);
int asciiValue = Integer.parseInt(hexByte, 16);
char asciiChar = (char) asciiValue;
asciiOutput.append(asciiChar);
// System.out.println("====接收转换消息====="+asciiOutput);
}
System.out.println("Start return");
HandleService handleService = new HandleService();
handleService.handle(asciiOutput.toString());
asciiOutput.setLength(0);
out.println("Server return json msg-->" + JSON.toJSONString(map));
}
System.out.println("=====接收消息====="+asciiOutput);
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println("----------------catch");
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
package com.gblfy.socketclent;
import org.springframework.stereotype.Service;
/**
* TCP 服务端逻辑处理类
*
* @author gblfy
* @Date 2023-08-03
**/
@Service
public class HandleService {
public void handle(String msg) {
//TODO 解析数据 落库
System.out.println("------------" + msg);
}
}
3.3. 客户端案例
package com.gblfy.socketclent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
public class SocketClient10004 {
public static void main(String[] args) throws IOException {
SocketClient("127.0.0.1", 10004, "111");
}
public static void SocketClient(String tcpServerIp, int tcpServerPort, String requestParam) throws IOException {
//1、创建客户端Socket
Socket socket = new Socket(tcpServerIp, tcpServerPort);
//2、向服务端发送数据
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
out.println(requestParam);
BufferedReader bufin = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String res = bufin.readLine();
System.out.println("------------>" + res);
socket.close();
}
}
3.4. nginx.conf
user root;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
# 加载/etc/nginx/conf.d/目录下以*.conf结尾的配置文件
include /etc/nginx/conf.d/*.conf;
}
stream {
server {
listen 8667;
proxy_pass tcp服务端IP:tpc服务端端口;
# proxy_pass 101.xxx.xxx.80:10004;
}
}
3.5. 调试
说明:网络调试助手->模拟飞机机载设备