在Java编程的世界中,网络通信是一个令人着迷的领域。无论是构建小型聊天应用还是实现复杂的分布式系统,掌握Socket编程都是至关重要的一步。然而,对于许多初学者来说,复杂的API和繁琐的实现细节往往让人望而却步。
下面是一个简单的使用Java实现Socket通信工具类的实现,希望对你有所帮助:
import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class SocketUtil {
private String host;
private int port;
/**
* 构造函数
*
* @param host 目标主机
* @param port 目标端口
*/
public SocketUtil(String host, int port) {
this.host = host;
this.port = port;
}
/**
* 发送XML请求并接收响应
*
* @param xmlRequest 要发送的XML报文
* @return 包含RetCode和RetDes的响应对象
* @throws Exception
*/
public Response sendAndReceive(String xmlRequest) throws Exception {
// 使用try-with-resources确保资源关闭
try (Socket socket = new Socket(host, port)) {
// 可以设置超时时间,例如10秒
socket.setSoTimeout(10000);
// 发送数据
OutputStream output = socket.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, StandardCharsets.UTF_8));
String message = formatMessage(xmlRequest);
writer.write(message);
writer.flush();
// 接收数据
InputStream input = socket.getInputStream();
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
// 通常使用Socket最前面会有报文长度,这里假设前8位是报文长度,读取前8位报文长度
byte[] lengthBytes = new byte[8];
int totalRead = 0;
while (totalRead < 8) {
int read = input.read(lengthBytes, totalRead, 8 - totalRead);
if (read == -1) {
throw new IOException("连接关闭,无法读取报文长度");
}
totalRead += read;
}
buffer.write(lengthBytes);
// 读取报文内容长度
String lengthStr = new String(lengthBytes, StandardCharsets.UTF_8);
int length = Integer.parseInt(lengthStr.trim());
// 读取报文内容
byte[] bodyBytes = new byte[length];
totalRead = 0;
while (totalRead < length) {
int read = input.read(bodyBytes, totalRead, length - totalRead);
if (read == -1) {
throw new IOException("连接关闭,无法读取完整报文");
}
totalRead += read;
}
buffer.write(bodyBytes);
// 输出缓存的所有内容
byte[] allContent = buffer.toByteArray();
System.out.println("接收到的全部内容:" + new String(allContent, StandardCharsets.UTF_8));
// 分别处理各个部分
String body = new String(bodyBytes, StandardCharsets.UTF_8);
System.out.println("报文内容:" + body);
// 解析XML
return parseXml(body);
}
}
// 示例方法,用于格式化消息
private String formatMessage(String xmlRequest) {
// 实现你的报文格式化逻辑,例如这里拼装发送报文的信息是8位报文长度+ 发送的xml格式报文
int length = xml.getBytes("UTF-8").length;
if (length > 99999999) {
throw new IllegalArgumentException("XML报文长度超过最大限制(99999999字节)");
}
String lengthStr = String.format("%08d", length);
return lengthStr + xml;
return xmlRequest;
}
// 示例方法,用于解析XML
private Response parseXml(String body) {
// 实现你的XML解析逻辑
// 这里示例获取xml格式报文的code,desc节点
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析XML内容
Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes("UTF-8")));
// 获取code节点
NodeList retCodeList = doc.getDocumentElement().getElementsByTagName("code");
String retCode = (retCodeList.getLength() > 0) ? retCodeList.item(0).getTextContent() : null;
// 获取code节点
NodeList retDesList = doc.getDocumentElement().getElementsByTagName("desc");
String retDes = (retDesList.getLength() > 0) ? retDesList.item(0).getTextContent() : null;
return new Response(retCode, retDes); // 返回一个示例响应对象
}
// 示例响应类
public static class Response {
private String retCode;
private String retDes;
public Response(String retCode, String retDes) {
this.retCode = retCode;
this.retDes = retDes;
}
public String getRetCode() {
return retCode;
}
public String getRetDes() {
return retDes;
}
@Override
public String toString() {
return "Response [RetCode=" + retCode + ", RetDes=" + retDes + "]";
}
}
public static void main(String[] args) {
try {
// 替换为实际的主机、端口和公司信息
SocketUtil socketUtil = new SocketUtil("127.0.0.1", 8080);
String xmlRequest = "<Request><Data>测试数据</Data></Request>";
Response response = socketUtil.sendAndReceive(xmlRequest);
System.out.println("响应结果: " + response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意
- 示例中使用byte类型接收返回的数据,也可以使用char类型,处理方式如下:
// 接收数据
InputStream input = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
// 读取前8位报文长度
char[] lengthChars = new char[8];
int totalRead = 0;
while (totalRead < 8) {
int read = reader.read(lengthChars, totalRead, 8 - totalRead);
if (read == -1) {
throw new IOException("连接关闭,无法读取报文长度");
}
totalRead += read;
}
String lengthStr = new String(lengthChars);
int length = Integer.parseInt(lengthStr);
// 读取报文内容
char[] bodyChars = new char[length];
totalRead = 0;
while (totalRead < length) {
int read = reader.read(bodyChars, totalRead, length - totalRead);
if (read == -1) {
throw new IOException("连接关闭,无法读取完整报文");
}
totalRead += read;
}
String body = new String(bodyChars);
使用char类型接收时需注意长度,中英文长度不同,会导致按长度读取出错。需通信双方提前约定。
- 文章使用
UTF-8
编码格式,具体的编码格式,需双方约定。