简体   繁体   English

Java TCP Socket While循环和计数器接收数据X次

[英]Java TCP Socket While loop and counter to receive data X times

I'm a amateur programmer and writing Java TCP socket client program that receives Integer and String type messages from the server(plc).我是一名业余程序员,正在编写 Java TCP 套接字客户端程序,它从服务器 (plc) 接收 Integer 和字符串类型的消息。 Currently it works fine and returns correct values if using basic try catch without any loops to keep the program running.目前,如果使用没有任何循环的基本 try catch 来保持程序运行,它可以正常工作并返回正确的值。

But... I've been trying to add while loop with counter of 5 receive times that ends the program after that but it returns on ONE read:但是......我一直在尝试添加 while 循环,计数器为 5 个接收时间,之后程序结束,但它在一次读取时返回:

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

How I should use the while loop in this case so it returns the correct values 5 times and then ends the program correctly?在这种情况下我应该如何使用 while 循环以便它返回正确的值 5 次然后正确结束程序?

My program looks like this:我的程序看起来像这样:

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


    }

}

EDIT:编辑:

Seems like if i change the received byte array length from [100] to [10], the program executes and prints this;似乎如果我将接收到的字节数组长度从 [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

EDIT #2编辑#2

So, I made server program that runs in localhost and sends byte[100] and it works correctly.因此,我制作了在 localhost 中运行并发送 byte[100] 的服务器程序,它工作正常。 Seems like problem is most likely in my PLC program, not in Java.似乎问题最有可能出现在我的 PLC 程序中,而不是 Java 中。

Server Class:服务器 Class:

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

in your while loop, you loop from 0 to 5, which means 6 times.在你的 while 循环中,你从 0 循环到 5,这意味着 6 次。 you may want to change this:你可能想改变这个:

while (counter <= 5)

to this, so that it loops only 5 times:为此,它只循环 5 次:

while (counter < 5)

You are not taking into account that the device sending the data (I'll refer to it as "server" for short) may close the stream on its end.您没有考虑到发送数据的设备(我将简称为“服务器”)可能会在其末端关闭stream。 When this happens, inFromServer.read() will return -1.发生这种情况时, inFromServer.read()将返回 -1。 You're not checking for this value, so you will end up filling the messageFromServer array with -1 values.您没有检查此值,因此您最终将使用 -1 值填充messageFromServer数组。

If you know that the messages are supposed to be 100 bytes, you can read a message with a single DataInputStream method call, without a for loop.如果您知道消息应为 100 字节,则可以通过单个DataInputStream方法调用读取消息,而无需 for 循环。 Replace your for (int i = 0; i < messageFromServer.length; i++) with:将您的for (int i = 0; i < messageFromServer.length; i++)替换为:

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

If the server stream is closed before the full message is read, this method will throw an exception (EOFException).如果服务器 stream 在读取完整消息之前关闭,则此方法将抛出异常 (EOFException)。

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

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