Java 套接字写入问题

Java socket write issues

我正在尝试创建一个 Modbus 设置,如下所示:

客户端 <----> IED <----> Modbus 服务器

IED 的 IP 为 192。168.x.x 并且 Modbus 服务器使用本地主机作为 IP。所有实体都在同一个虚拟机中。客户端应该向IED发送请求,IED将其转发给服务器,服务器响应IED。

问题是 IED 从存储在字节数组中的主机接收到请求,但无法将请求传输到服务器。 Wireshark 跟踪显示与服务器建立了 TCP 连接,但未传输请求。

查看下面的代码:

public class App {
    public static void main(String[] args) {
        IEDServer iedServer = new IEDServer();
        iedServer.start(502);
    }    
}

import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;

public class IEDServer {
    private ServerSocket serverSocket;

    public void start (int port){
        try {
            InetAddress inetAddress = InetAddress.getByName("192.168.20.138");
            serverSocket = new ServerSocket(port, 1024, inetAddress);
            while (true){
                new ClientHandler(serverSocket.accept()).start();
                System.out.println("Connection accepted");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void stop(){
        try {
            serverSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

import java.io.*;
import java.net.Socket;

public class ClientHandler extends Thread{
    private Socket clientSocket;

    private DataOutputStream out;
    private DataInputStream in;


    public ClientHandler(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() {
        try {
            //connection from client
            out = new DataOutputStream (clientSocket.getOutputStream());
            in = new DataInputStream(clientSocket.getInputStream());
//            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//            String readline;

            //for connection to modbus server
            Socket modbusSocket = new Socket("127.0.0.1",502);
            modbusSocket.setSoTimeout(10000);
            DataOutputStream modbus_out = new DataOutputStream (clientSocket.getOutputStream());
            DataInputStream modbus_in = new DataInputStream(clientSocket.getInputStream());
            byte [] modbus_bytes = {};

            //read Modbus bytes from client to get client request
            modbus_bytes = in.readAllBytes();

            System.out.println("Modbus request: ");
            for (byte b: modbus_bytes){
                System.out.print(b);
            }
            System.out.println();

            //transfer modbus request to modbus server
            modbus_out.write(modbus_bytes, 0, modbus_bytes.length);

            //get response from modbus server
            modbus_bytes = modbus_in.readAllBytes();

            System.out.println("Modbus response: ");
            for (byte b: modbus_bytes){
                System.out.print(b);
            }
            System.out.println();

            //transfer response to client
            out.write(modbus_bytes,0,modbus_bytes.length);

        } catch (IOException e) {
            e.printStackTrace();
        }

        //close TCP connection
        try {
            in.close();
            out.close();
            clientSocket.close();
            System.out.println("Connection terminated");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Connection termination failed");
        }
    }
}

下面还有wireshark截图

DataOutputStream.write()之后调用DataOutputStream.flush()强制发送字节

我设法修复了它。我错误地将 clientSocket 而不是 modbusSocket 作为参数传递给了 modbus_inmodbus_outStream 实例。在读取和写入之前,我还必须轮询数据的可用性。另外,我注意到客户端关闭了 TCP 会话,而服务器端打开了它。所以我确保在每次查询后关闭连接。

请在下面找到 ClientHandler 的修改代码:

import java.io.*;
import java.net.Socket;

public class ClientHandler extends Thread {
    private Socket clientSocket;
    private Socket modbusSocket;

    private DataOutputStream out, modbus_out;
    private DataInputStream in, modbus_in;

    public ClientHandler(Socket clientSocket) {
        this.clientSocket = clientSocket;
        System.out.println(clientSocket.getInetAddress());

        try {
            out = new DataOutputStream(new BufferedOutputStream(clientSocket.getOutputStream()));
            in = new DataInputStream(new BufferedInputStream(clientSocket.getInputStream()));

//            in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//            String readline;

            //for connection to modbus server
            modbusSocket = new Socket("127.0.0.1", 502);
            //            modbusSocket.setSoTimeout(10000);
            modbus_out = new DataOutputStream(new BufferedOutputStream(modbusSocket.getOutputStream()));
            modbus_in = new DataInputStream(new BufferedInputStream(modbusSocket.getInputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            //connection from client
            if (in.available() > 0) {
                //read Modbus bytes from client to get client request
                System.out.println("===============Begin reading===============");
                byte[] modbus_bytes = new byte[in.available()];
                in.read(modbus_bytes);
                System.out.println("Modbus request: ");
                for (byte b : modbus_bytes) {
                    System.out.print(b);
                }
                System.out.println();

                //transfer modbus request to modbus server
                modbus_out.write(modbus_bytes);
                modbus_out.flush();
                System.out.println("Written to modbus server");

                while (modbus_in.available() == 0) {
                    System.out.println("Waiting for device response...");
                }
                System.out.println("\nDevice response ready");

                //get response from modbus server
                modbus_bytes = new byte[modbus_in.available()];
                modbus_in.read(modbus_bytes);

                System.out.print("Modbus response: ");
                for (byte b : modbus_bytes) {
                    System.out.print(b);
                }
                System.out.println("\nSending response to client");

                //transfer response to client
                out.write(modbus_bytes);
                out.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        //close TCP connection
        try {
//            in.close();
//            out.close();
            clientSocket.close();
            modbusSocket.close();
            System.out.println("===========Connection terminated==============");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("Connection termination failed");
        }
    }
}