【问题标题】:Java sockets DataInputStream reading uninitialized dataJava sockets DataInputStream 读取未初始化的数据
【发布时间】:2017-02-27 21:06:10
【问题描述】:

我正在尝试实现客户端-服务器通信。 我尝试了异步的,现在我正在绑定同步的,但只是为了让它工作。我尽可能多地切断了不必要的代码,即使经过一天的研究,我也无法让它工作。拜托,如果你能救我,我将不胜感激!

我现在将说明问题并指出代码的某些部分,请理解所有代码都在下面提供

问题: 在 main.java 中

我创建一个服务器和客户端,然后发送数据。

s.InitiateRead()

是一个函数,它只会永远循环并尝试从 DataInputStream 中读取一个 int

len = BReaderForClient.readInt();

你也可以看到类似的代码

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

这仅发送数字 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);
    }
}

如您所见,我有用于从多个线程写入的信号量。

所以我写了 3 次 Integer 到流,然后我在线程中调用读,然后继续写更多。 这个测试的重点是用数据淹没套接字,就好像你在每次发送之间放置 Thread.Sleep(5000) 一样,一切都会好的。

问题是,运行时,有时读取的输出不是预期的 12 号。

请注意,在 main.java 中注释的 while 循环可以取消注释,仍然给出错误的输出(只是说如果主线程结束,它会杀死所有其他线程)

所有代码:

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)
        {}*/
    }
}

服务器.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;
}

客户端.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(通用库)

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

程序的输出:

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

如您所见,有时它会读取 0,甚至是一些未初始化的值。 拜托,你能帮帮我吗?我无法解释也无法理解,这到底是怎么可能的。 我对我正在使用的所有函数进行了红色文档,但这仍然是一个谜。

非常感谢您提供任何可能的帮助

【问题讨论】:

  • 虽然它本身显然不能解决问题,但在 Java 中使用 camel case 几乎是 generally accepted convention 并且适用于 JDK。我建议坚持下去。
  • 这里没有信号量,只有一个布尔变量,这还不够。您应该使用同步、等待/通知或适当的信号量。

标签: java sockets


【解决方案1】:

您正在 Listen 方法中启动一个线程,该线程在无限循环中调用 Accept_begin -> Accept_end -> Accept_begin -> ...。

在 Accept_end 中,你不断地替换 BReaderForClient 和 writer。这里似乎有些不对劲。

另外,你正在做并行编程。您的发送方法需要同步。

【讨论】:

  • 是的,听着我就知道了,以后我想接受更多的客户。 send 方法....在我看来,应该使用布尔变量 CurrentWritingToOutputStream 充分完成同步,因为一次只有一个线程会写入线程...
  • 哇,非常感谢。我在 Google 上搜索了同步,发现可以使用 synchronized 关键字在 Java 中完成。到目前为止,当我运行程序 12 次时,我仍然得到相同的输出。谢谢。
猜你喜欢
  • 2020-07-28
  • 2023-03-31
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 2018-07-20
  • 1970-01-01
  • 2019-02-19
  • 2016-07-20
相关资源
最近更新 更多