Jan Glaser Jan Glaser -4 years ago 135
Java Question

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

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

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):

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.
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.

The problem is, when runs, sometimes the read output is not number 12, as expected.

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)

All code:

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

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

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)

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.
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

Answer Source

You are starting a thread in Listen method which calls Accept_begin -> Accept_end -> Accept_begin -> ... in infinite loop.

In Accept_end, you are keep on replacing BReaderForClient and writer continuously. Seems something wrong here.

Also, you are doing parallel programming. Your send method needs to be synchronized.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download