【问题标题】:Java TCP Socket While loop and counter to receive data X timesJava TCP Socket While循环和计数器接收数据X次
【发布时间】:2020-11-24 11:23:03
【问题描述】:

我是一名业余程序员,正在编写从服务器(plc)接收整数和字符串类型消息的 Java TCP 套接字客户端程序。目前,如果使用没有任何循环的基本 try catch 来保持程序运行,它可以正常工作并返回正确的值。

但是...我一直在尝试添加带有 5 个接收时间的计数器的 while 循环,之后程序结束,但它在 ONE 读取时返回:

Int: 705 //correct value that it should receive every time
String: testi3 //correct value that it should receive every time



Int: 0 // prints also this duplicate value
String:  // prints also this duplicate value

在这种情况下我应该如何使用 while 循环,以便它返回正确的值 5 次,然后正确结束程序?

我的程序如下所示:

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

public class GetData2 {

    private static int counter =0;
    private Socket clientSocket;
    //private PrintWriter out;
    private String host = "192.168.0.1";
    private int port2 = 2000;
    private DataInputStream inFromServer;




    public void start() throws IOException{
        System.out.println("Client started");
        clientSocket = new Socket(host, port2);
    }




    public void run() throws IOException {

        while (counter <= 5) {

            inFromServer = new DataInputStream(clientSocket.getInputStream());
            //BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

            int length = 100; // read length of incoming message
            byte[] messageFromServer = new byte[length];


                for (int i = 0; i < messageFromServer.length; i++) {
                    messageFromServer[i] = (byte) inFromServer.read();             //read message from the server
                }
                System.out.println("\n");

                //System.out.println(Arrays.toString(messageFromServer));
                byte[] copyOfData = Arrays.copyOf(messageFromServer, messageFromServer.length); //copies byte array from messageFromServer[] to copyOfData[]



                System.out.println("\n");
                //Integer
                short value = 0;
                                                                                            // reads bytes 0-1
                value = (short) (copyOfData[0] * 256 + (short) copyOfData[1]);              // moves received bytes
                                                                                          // shows the order of received byes

                System.out.println("Int: " + value);                                     // return bytes as an Integer

                //String
                System.out.print("String: ");
                for (int i = 4; i < copyOfData.length && i < 10; i++) {            // reads bytes 4-10 from array

                    System.out.printf("%c", copyOfData[i]);                   // returns String testi2 from pythondemo 2 plc application
                }
                counter++;
            System.out.println(counter);



        }


    }
    public void stop() throws IOException{

        //out.close();

        System.out.println("Application stopped");
        clientSocket.close();
        inFromServer.close();

    }




    public static void main(String[] args) throws IOException {
        GetData2 getData2 =new GetData2();
        getData2.start();
        getData2.run();


        if(counter == 5){
            getData2.stop();
        }


    }

}

编辑:

好像如果我将接收到的字节数组长度从 [100] 更改为 [10],程序就会执行并打印它;

Client started




Int: 705
String: testi3
counter: 1




Int: 0
String:       
counter: 2




Int: 0
String:       
counter: 3




Int: 0
String:       
counter: 4




Int: 0
String:       
counter: 5
Application stopped

编辑#2

所以,我制作了在 localhost 中运行并发送 byte[100] 的服务器程序,它可以正常工作。似乎问题很可能在我的 PLC 程序中,而不是在 Java 中。

服务器类:

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class GetData2_Server {
    public static void main(String[] args) throws IOException {
        System.out.println("server started");
        Scanner scan = new Scanner(System.in);
        ServerSocket server = new ServerSocket(8080);
        Socket socket = server.accept();
        System.out.println("server accepted");
        System.out.println("1 == out n flush, 0 == close program");
        int value = scan.nextInt();
        byte[] bytesOut = new byte[100];
        bytesOut[0]=0;
        bytesOut[1]=3;

        DataOutputStream out = new DataOutputStream(socket.getOutputStream());

        while (value == 1)
            {
                out.write(bytesOut);
                out.flush();
                value = scan.nextInt();
                if(value == 0){
                    out.close();
                    socket.close();
                }
            }
    }
}

【问题讨论】:

  • 服务器真的发送了5份消息吗?
  • 目前字节数组是由控制何时向Java客户端发送数据的物理开关发送的。我其实很好奇为什么它会再次调用该方法。
  • 那么它是否发送多条消息?
  • 哎呀,删除了答案。但是不,它一次只发送一条消息。

标签: java sockets tcp tcpclient


【解决方案1】:

在您的 while 循环中,您从 0 循环到 5,这意味着 6 次。 你可能想改变这个:

while (counter <= 5)

到此,使其仅循环 5 次:

while (counter < 5)

【讨论】:

  • 您好,感谢您的回答。这是真的,但不是主要情况。基本上,现在 While 循环每次服务器发送字节数组时都会打印一次正确的值,并打印一份带有空值的副本。它应该每次只打印那里标记的正确值。
【解决方案2】:

您没有考虑到发送数据的设备(我将其简称为“服务器”)可能会在其末端关闭流。发生这种情况时,inFromServer.read() 将返回 -1。您没有检查此值,因此您最终将使用 -1 值填充 messageFromServer 数组。

如果您知道消息应该是 100 字节,则可以使用单个 DataInputStream 方法调用来读取消息,而无需 for 循环。更换你的 for (int i = 0; i &lt; messageFromServer.length; i++) 与:

byte[] messageFromServer = new byte[length];
inFromServer.readFully(messageFromServer);

如果在读取完整消息之前关闭服务器流,则此方法将抛出异常(EOFException)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-08
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 2016-04-02
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多