简体   繁体   English

通过 XML(Java、TCP)进行客户端-服务器通信

[英]Client-Server communication via XML (Java, TCP)

i have written a client - server programm, where different clients and server communicate via request/reply using xml and tcp sockets.我编写了一个客户端-服务器程序,其中不同的客户端和服务器使用 xml 和 tcp sockets 通过请求/回复进行通信。 Later i want to add udp sockets.稍后我想添加 udp sockets。 This is the current code:这是当前代码:

Client:客户:

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);
        }
    }
}

Server:服务器:

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();
    }
}

RequestHandler:请求处理程序:

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: XML 请求:

<Request>
  <Info Attribute1="" Attribute2=""></Info>
  <Info Attribute1="" Attribute2=""></Info>
</Request>

XML Reply (the overhead sending back the attributes will be necessary for the client, so i have to send it twice): XML 回复(客户端需要发送回属性的开销,所以我必须发送两次):

<Reply>
  <Info Attribute1="" Attribute2="">GoodReply</Info>
  <Info Attribute1="" Attribute2="">GoodReply</Info>
</Reply>

My question is 2-folded:我的问题是双重的:

1.) Maybe I did something unusual at the client-server programming (forgetting to close something, unusual stream reading/handling). 1.)也许我在客户端-服务器编程中做了一些不寻常的事情(忘记关闭某些东西,不寻常的 stream 读取/处理)。 Reading every line of the client/server message seems to be eg weird for me, because i'd rather read the xml message until it is finished independently of its line).阅读客户端/服务器消息的每一行对我来说似乎很奇怪,因为我宁愿阅读 xml 消息,直到它独立于其行完成)。 Feel free to provide me "good coding style" advice:-)随时为我提供“良好的编码风格”建议:-)

2.) At the moment i would assemble the XML by a StringBuilder and send just the bytes of the whole String and without special characters like \r \n. 2.) 目前我将通过 StringBuilder 组装 XML 并仅发送整个字符串的字节,而不发送特殊字符,如 \r \n。 I'm not sure how to do it with a common api like Stax (this seemed to be complicated).我不确定如何使用像 Stax 这样的常见 api 来做到这一点(这似乎很复杂)。 Parsing the Attributes and their content will be necessary for the application.应用程序需要解析属性及其内容。 Is there an easier/more common way to solve this?有没有更简单/更常见的方法来解决这个问题? If not: how to do it with eg Stax?如果没有:如何使用例如 Stax 来做到这一点?

Good question!好问题!

Since TCP is a streaming protocol, you don't really know where the message begins and where it ends, unless you specify that each connect/disconnect contains exactly one message, or that you specify some delimiting mechanism (a framing protocol).由于 TCP 是一种流式协议,因此您并不真正知道消息在哪里开始和在哪里结束,除非您指定每个连接/断开连接仅包含一条消息,或者您指定了一些定界机制(帧协议)。 Actually, it might be easier to start with UDP, since a datagram could contain the entire message in itself.实际上,从 UDP 开始可能更容易,因为数据报本身可以包含整个消息。

As for the framing protocol, an example is the Using the NETCONF Protocol over Secure Shell specification.至于成帧协议,一个例子是Using the NETCONF Protocol over Secure Shell规范。 You can of course devise your own framing.您当然可以 devise 您自己的框架。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM