简体   繁体   English

Java套接字DataInputStream读取未初始化的数据

[英]Java sockets DataInputStream reading uninitialized data

I am trying to implement a client - server communication. 我正在尝试实现客户端-服务器通信。 I tried asynchronous one, now I am tying synchronous one, but just to make it work. 我尝试了异步同步,但现在我将同步同步捆绑在一起,但是只是为了使其工作。 I cut off as much unnecesarry code as possible, and even after day of research, i am unable to make it work. 我切断了尽可能多的不必要的代码,即使经过一天的研究,我也无法使其正常工作。 Please, if you could save me, I would really appreciate it! 拜托,如果您能救我,我将不胜感激!

I will now specify the problem and point out some parts of code, uderstanding that all code is provided below 现在,我将说明问题并指出代码的某些部分,因为下面提供了所有代码

The problem: In main.java 问题:在main.java中

I create a server and client, and I send data. 创建服务器和客户端,然后发送数据。

s.InitiateRead()

Is a function, that only loops forever and tries to read an int from DataInputStream 是一个函数,只会永远循环并尝试从DataInputStream读取int

len = BReaderForClient.readInt();

You can also see code like 您还可以看到类似的代码

c.Send(ByteBuffer.wrap("A".getBytes()));

This sends only number 12, not any A or something, method that is finally called (in thread) is this (located in ClientServerBase.java): 这仅发送数字12,而不发送任何A或其他任何东西,最终(在线程中)调用此方法(位于ClientServerBase.java中):

void Send_Begin(ByteBuffer Data, DataOutputStream OutputStream) {
    try {
        while(CurrentlyWritingToOutputStream)
        { /* wait */ }

        CurrentlyWritingToOutputStream = true;

        OutputStream.writeInt(12);
        OutputStream.flush();

        CurrentlyWritingToOutputStream = false;

        Send_End(false);
    } catch (IOException e) {
        Send_End(true);
    }
}

As you see, I have semaphore for writing from multiple threads. 如您所见,我有从多个线程进行写操作的信号灯。

So I write 3 times Integer to stream, then I call reading in thread, and then continue writing some more. 因此,我写了3次Integer进行流传输,然后调用线程读取,然后继续编写更多内容。 The point of this test was to flood the sockets with data, as if you would put Thread.Sleep(5000) between each send, all would be ok. 该测试的重点是向套接字充斥数据,就像您将Thread.Sleep(5000)放在每个发送之间一样,一切正常。

The problem is, when runs, sometimes the read output is not number 12, as expected. 问题是,在运行时,有时读取的输出不是预期的12号。

Please notice, that the while loop that is commented in main.java can be uncommented, still giving wrong output (just saying that if main thread ends, it kills all other threads) 请注意,main.java中注释的while循环可以取消注释,但仍给出错误的输出(只是说如果主线程结束,它将杀死所有其他线程)

All code: 所有代码:

main.java main.java

package net;

import java.nio.ByteBuffer;

public class main {
    public static void main(String[] args) throws Exception {

        Server s = new Server();
        s.Start();
        if(!s.Listen())
            return;


        Client c = new Client();

        c.Send(ByteBuffer.wrap("A".getBytes()));
        c.Send(ByteBuffer.wrap("A".getBytes()));
        c.Send(ByteBuffer.wrap("A".getBytes()));

        new Thread(new Runnable() {
            public void run() {
                s.InitiateRead();
            }
        }).start();

        c.Send(ByteBuffer.wrap("A".getBytes()));
        c.Send(ByteBuffer.wrap("A".getBytes()));
        c.Send(ByteBuffer.wrap("A".getBytes()));

        /*while(true)
        {}*/
    }
}

Server.java 服务器.java

package net;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;

public class Server extends ClientServerBase {
    public Server()
    {
        super(ClientServerBase.REAL_TYPE.SERVER);
    }

    // ======================================================================================
    void Accept_Begin() {
        Socket socket = null;
        try {
            socket = serverSocket.accept();
        } catch (IOException e) {
            Accept_End(true, socket);
            return;
        }
        Accept_End(false, socket);
    }
    public void InitiateRead()
    {
        while(true){

        int len = 0;
        try {
            len = BReaderForClient.readInt();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Print("Red: " + len);
        }
    }

    void Accept_End(boolean error, Socket acceptedclient) {
        try {
            if (!error) {
                Print("Client accepted");
                Clientsock = acceptedclient;

                BwriterForClient = new DataOutputStream(acceptedclient.getOutputStream());
                BReaderForClient = new DataInputStream(acceptedclient.getInputStream());
            }

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

    public void close() throws IOException {
        BwriterForClient.close();
        Clientsock.close();
        serverSocket.close();
    }

    public boolean Listen() {
        if(serverSocket == null)
        {
            Print("Can not listen, Start() was not called.");
            return false;
        }

        new Thread(new Runnable() {
            public void run() {
                Accept_Begin();
            }
        }).start();

        return true;
    }

    public boolean Start()
    {
        try 
        {
            serverSocket = new ServerSocket(1254);
        } 
        catch (IOException e) 
        {
            Print("Can not host, port is probably already in use");
            return false;
        }
        return true;
    }
    public void Send(ByteBuffer b) {
        Send_In_Thread(b, BwriterForClient);
    }

    Socket Clientsock;
    ServerSocket serverSocket;
    DataOutputStream BwriterForClient;
    DataInputStream BReaderForClient;
}

Client.java 客户端.java

package net;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;

public class Client extends ClientServerBase {
    public Client() throws UnknownHostException, IOException 
    {
        super(ClientServerBase.REAL_TYPE.CLIENT);

        ClientSocket = new Socket("localhost", 1254);
        DIS = new DataInputStream(ClientSocket.getInputStream());
        DOS = new DataOutputStream(ClientSocket.getOutputStream());

        //Read_In_Thread(DIS);
    }

    public void close() throws IOException {
        DIS.close();
        DOS.close();
        ClientSocket.close();
    }


    /**
     * @brief Sends data to the server. That is done in thread
     * @param Data
     */

    public void Send(ByteBuffer Data) {
        Send_In_Thread(Data, DOS);
    }


    Socket ClientSocket;
    DataInputStream DIS;
    DataOutputStream DOS;
}

ClientServerBase.java (common base) ClientServerBase.java(通用库)

package net;

import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public abstract class ClientServerBase {
    protected enum REAL_TYPE
    {
        CLIENT,
        SERVER
    }

    protected ClientServerBase(final REAL_TYPE r)
    {   
        CurrentlyWritingToOutputStream = false;
        ReadThreadRunning = false;
        real_type = r;
    }

    //=============================================================================

    protected void Print(String s)
    {
        if(real_type == REAL_TYPE.CLIENT)
            s = "Client: " + s;
        else
            s = "Server: " + s;
        System.out.println(s);
    }   

    void Send_Begin(ByteBuffer Data, DataOutputStream OutputStream) {
        try {
            while(CurrentlyWritingToOutputStream)
            { /* wait */ }

            CurrentlyWritingToOutputStream = true;

            OutputStream.writeInt(12);
            OutputStream.flush();

            CurrentlyWritingToOutputStream = false;

            Send_End(false);
        } catch (IOException e) {
            Send_End(true);
        }
    }

    void Send_End(boolean Error) {
        if (!Error)
            Print("Data sent sucessfully");
        else
            Print("There was an error sending data");
    }

    protected void Send_In_Thread(ByteBuffer Data, DataOutputStream OutputStream) {
        new Thread(new Runnable() {
            public void run() {
                Send_Begin(Data, OutputStream);
            }
        }).start();
    }

    boolean ReadThreadRunning;
    boolean CurrentlyWritingToOutputStream;
    /**
     * Real type of object
     */
    REAL_TYPE real_type;
}

The output of program: 程序输出:

Server: Client accepted
Client: Data sent sucessfully
Client: Data sent sucessfully
Client: Data sent sucessfully
Server: Red: 12
Server: Red: 0
Client: Data sent sucessfully
Client: Data sent sucessfully
Server: Red: 3084
Client: Data sent sucessfully
Server: Red: 12
Server: Red: 0
Server: Red: 201326604

As you see, sometimes, it reads 0, and even some uninitialised values. 如您所见,有时它读取0,甚至读取一些未初始化的值。 Please, can you help me? 拜托,你能帮我吗? I can not explain nor understand, how on the earth is this possible. 我无法解释也无法理解,这到底是怎么可能的。 I red documentation of all functions I am using, still, this is a mystery. 我仍在整理所有我正在使用的所有功能的文档,这仍然是个谜。

Thank you very much for any possible help 非常感谢您的任何帮助

You are starting a thread in Listen method which calls Accept_begin -> Accept_end -> Accept_begin -> ... in infinite loop. 您正在用Listen方法启动一个线程,该线程在无限循环中调用Accept_begin-> Accept_end-> Accept_begin->...。

In Accept_end, you are keep on replacing BReaderForClient and writer continuously. 在Accept_end中,您将继续不断替换BReaderForClient和writer。 Seems something wrong here. 这里似乎有问题。

Also, you are doing parallel programming. 另外,您正在执行并行编程。 Your send method needs to be synchronized. 您的发送方法需要同步。

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

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