【发布时间】:2021-07-29 03:01:05
【问题描述】:
我编写了一个客户端-服务器程序,其中不同的客户端和服务器使用 xml 和 tcp 套接字通过请求/回复进行通信。稍后我想添加 udp 套接字。这是当前代码:
客户:
package network.client;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class Client implements Closeable {
private Socket socket;
public Client(String host, int port) throws IOException {
this(new Socket(host, port));
}
public Client(Socket s) {
this.socket = s;
}
@Override
public void close() throws IOException {
this.socket.close();
}
public void send(String msg) throws IOException {
OutputStream out=this.socket.getOutputStream();
out.write(msg.getBytes());
out.flush();
socket.shutdownOutput();
}
public void recv() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String request="";
String temp=in.readLine();
while(temp!=null) {
request+=temp;
temp=in.readLine();
}
socket.shutdownInput();
System.out.println("Client: " + request);
System.out.println(request.toString().length());
} catch (IOException ex) {
System.err.println("Error: Unable to read server response\n\t" + ex);
}
}
public static void main(String[] args) {
// Make sure command line arguments are valid
String ip="127.0.0.1";
int port=5000;
StringBuilder sb = new StringBuilder();
sb.append("stuff");
System.out.println(sb.toString().length());
try (Client c = new Client(ip, port)) {
c.send(sb.toString());
c.recv();
c.close();
} catch (IOException ex) {
System.err.println("Error: " + ex);
}
}
}
服务器:
package network.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server {
private static ServerSocket serversocket;
private static ExecutorService threadpool;
private String ip;
private int port;
public static void main(final String[] args) {
Server2 server;
String ip = "127.0.0.1";
int port = 5000;
try {
server = new Server(ip, port);
while (true) {
Runnable requestHandler = null;
try {
requestHandler = new TCPRequestHandler(serversocket.accept());
} catch (IOException io) {
System.out.println("Accepting client connection failed");
io.printStackTrace();
}
threadpool.submit(requestHandler);
}
} catch (IOException io) {
System.out.println(io.getMessage());
io.printStackTrace();
}
System.out.println("end");
}
public Server(String ip, int port) throws IOException {
this.ip = ip;
this.port = port;
try {
this.serversocket = new ServerSocket();
serversocket.bind(new InetSocketAddress(ip, port));
} catch (IOException io) {
throw new IOException("Creating the ServerSocket failed");
}
System.out.println("Binding the server succeeded");
this.threadpool = Executors.newCachedThreadPool();
}
}
请求处理程序:
public class TCPRequestHandler extends Thread{
private Socket clientSocket=null;
public TCPRequestHandler(Socket clientSocket) {
this.clientSocket=clientSocket;
}
public void run(){
System.out.println("Accepted client connection (" + clientSocket.getInetAddress().getHostAddress() + ", " + clientSocket.getPort() + ")");
byte[] buffer = new byte[1024];
int count;
try {
BufferedReader in =new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
OutputStream out = clientSocket.getOutputStream();
String request="";
String temp=in.readLine();
while(temp!=null) {
request+=temp;
temp=in.readLine();
}
System.out.println("Server:" + request);
System.out.println(request.toString().length());
// do stuff with xml request
out.write(request.getBytes());
out.flush();
clientSocket.shutdownInput();
clientSocket.shutdownOutput();
} catch (IOException io) {
System.err.println("IO initialization failed");
}
}
}
XML 请求:
<Request>
<Info Attribute1="" Attribute2=""></Info>
<Info Attribute1="" Attribute2=""></Info>
</Request>
XML 回复(客户端需要发送回属性的开销,所以我必须发送两次):
<Reply>
<Info Attribute1="" Attribute2="">GoodReply</Info>
<Info Attribute1="" Attribute2="">GoodReply</Info>
</Reply>
我的问题是两方面的:
1.) 也许我在客户端-服务器编程中做了一些不寻常的事情(忘记关闭某些东西,不寻常的流读取/处理)。阅读客户端/服务器消息的每一行似乎是例如对我来说很奇怪,因为我宁愿阅读 xml 消息,直到它独立于它的行完成)。随时为我提供“良好的编码风格”建议 :-)
2.) 目前,我将通过 StringBuilder 组装 XML,并仅发送整个字符串的字节,而不发送像 \r \n 这样的特殊字符。我不确定如何使用像 Stax 这样的通用 api 来做到这一点(这似乎很复杂)。应用程序需要解析属性及其内容。有没有更简单/更常见的方法来解决这个问题? 如果没有:如何使用例如 Stax?
【问题讨论】: