bganoush
asked on
Scope of thread?
Can anyone tell me what is the scope of a thread and socket... I am encountering a problem where data returned from my server application is being dropped midway through it. I think maybe the problem is related to garbage collection and object scope.
The following code will listen for a message from a client, then in the ReadWriteSocketThread, it reads the given socket(within run()) and responds with lots of data (3000+ bytes) using the socket.getOutputStream().. . It flushes the stream at every 180 bytes or so. The problem is that the client only receives events for 1 to n of these "flushes"... and sometimes it receives the entire stream.
public class MyServerApplication
{
public MyServerApplication()
{
try
{
int listenPort = 800;
ServerSocket serverSocket = new ServerSocket(listenPort);
// For each new connection start a thread to handle it
while (true)
{
Socket s = serverSocket.accept();
System.out.println("Creati ng a local thread");
ReadWriteSocketThread thread = new ReadWriteSocketThread (s);
thread.start();
}
}
catch (Exception e)
{
System.out.println("Except ion");
e.printStackTrace();
}
}
public static void main (String args[])
{
MyServerApplication server = new MyServerApplication();
}
}
public class ReadWriteSocketThread extends Thread
{
public void run()
{
try
{
int b;
int len;
byte[] bt = new byte[4];
String startMessage = new String ("*START*");
BufferedInputStream in = new BufferedInputStream(mySock et.getInpu tStream()) ;
StringBuffer sb = new StringBuffer();
boolean isValid = false;
if (in.read(bt, 0, 4) == 4)
{
len = bt[0] * 256 + bt[1];
System.out.println("Length of string: " + len);
for (int i = 0; i < len; i ++)
{
b = in.read();
if (b == -1)
break;
sb.append((char)b);
}
System.out.println("String : " + sb.toString());
if (sb.toString().equals(star tMessage))
{
isValid = true;
}
}
if (isValid && in.read(bt, 0, 4) == 4)
{
sb.setLength(0);
len = bt[0] * 256 + bt[1];
System.out.println("Length of string: " + len);
for (int i = 0; i < len; i ++)
{
b = in.read();
if (b == -1)
break;
sb.append((char)b);
}
System.out.println("String : " + sb.toString());
}
if (isValid)
{
if (in.read(bt, 0, 4) == 4)
{
len = bt[0] * 256 + bt[1];
if (len != 4)
{
ErrorLog eLog = new ErrorLog(m_Config);
eLog.log("Error reading from socket: Message end tag was not found.");
}
}
}
System.out.println("Receiv ed: " + sb.toString());
// SEND BACK A RESPONSE IN PIECES:
Responder makeAnswer = new Responder(sb.toString());
BufferedOutputStream out = new BufferedOutputStream(mySoc ket.getOut putStream( ));
int numResponses = makeAnswer.getNumResponses ();
System.out.println("NumRes ponses: " + numResponses);
// numResponses is typically between 15 and 18:
for (int i = 0; i < numResponses; i ++)
{
// response is typically 180 bytes on a good day:
String response = makeAnswer.getResponse(i);
//System.out.println ("response: "+ response);
//System.out.println ("length: "+ response.length());
int lenOut = response.length()+2;
out.write(lenOut / 256);
out.write(lenOut);
for (int j=0;j<response.length();j+ +)
out.write((byte)(response. charAt(j)) );
out.write(0);
out.flush();
}
out.close();
in.close();
m_oSocket.close();
} catch (IOException e) {
//System.out.println ("IOException in Thread");
ErrorLog eLog = new ErrorLog(m_Config);
eLog.log("Error reading from socket: "+e.getMessage());
}
}
}
The following code will listen for a message from a client, then in the ReadWriteSocketThread, it reads the given socket(within run()) and responds with lots of data (3000+ bytes) using the socket.getOutputStream()..
public class MyServerApplication
{
public MyServerApplication()
{
try
{
int listenPort = 800;
ServerSocket serverSocket = new ServerSocket(listenPort);
// For each new connection start a thread to handle it
while (true)
{
Socket s = serverSocket.accept();
System.out.println("Creati
ReadWriteSocketThread thread = new ReadWriteSocketThread (s);
thread.start();
}
}
catch (Exception e)
{
System.out.println("Except
e.printStackTrace();
}
}
public static void main (String args[])
{
MyServerApplication server = new MyServerApplication();
}
}
public class ReadWriteSocketThread extends Thread
{
public void run()
{
try
{
int b;
int len;
byte[] bt = new byte[4];
String startMessage = new String ("*START*");
BufferedInputStream in = new BufferedInputStream(mySock
StringBuffer sb = new StringBuffer();
boolean isValid = false;
if (in.read(bt, 0, 4) == 4)
{
len = bt[0] * 256 + bt[1];
System.out.println("Length
for (int i = 0; i < len; i ++)
{
b = in.read();
if (b == -1)
break;
sb.append((char)b);
}
System.out.println("String
if (sb.toString().equals(star
{
isValid = true;
}
}
if (isValid && in.read(bt, 0, 4) == 4)
{
sb.setLength(0);
len = bt[0] * 256 + bt[1];
System.out.println("Length
for (int i = 0; i < len; i ++)
{
b = in.read();
if (b == -1)
break;
sb.append((char)b);
}
System.out.println("String
}
if (isValid)
{
if (in.read(bt, 0, 4) == 4)
{
len = bt[0] * 256 + bt[1];
if (len != 4)
{
ErrorLog eLog = new ErrorLog(m_Config);
eLog.log("Error reading from socket: Message end tag was not found.");
}
}
}
System.out.println("Receiv
// SEND BACK A RESPONSE IN PIECES:
Responder makeAnswer = new Responder(sb.toString());
BufferedOutputStream out = new BufferedOutputStream(mySoc
int numResponses = makeAnswer.getNumResponses
System.out.println("NumRes
// numResponses is typically between 15 and 18:
for (int i = 0; i < numResponses; i ++)
{
// response is typically 180 bytes on a good day:
String response = makeAnswer.getResponse(i);
//System.out.println ("response: "+ response);
//System.out.println ("length: "+ response.length());
int lenOut = response.length()+2;
out.write(lenOut / 256);
out.write(lenOut);
for (int j=0;j<response.length();j+
out.write((byte)(response.
out.write(0);
out.flush();
}
out.close();
in.close();
m_oSocket.close();
} catch (IOException e) {
//System.out.println ("IOException in Thread");
ErrorLog eLog = new ErrorLog(m_Config);
eLog.log("Error reading from socket: "+e.getMessage());
}
}
}
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
NovaDenizen, I think you posted to the wrong thread. And the fact that byte is a signed datatype is not exactly a revelation!
oops.
No, this was the right thread, and this is a serious problem in his code. This is how he was calculating the number of bytes to read.
When length < 32768 and (length % 256) >= 128, this bug would cause premature ending of the loop that is reading in data one character at a a time.
When length < 32768 and (length % 256) < 128, there would not be any obvious bug, and the complete buffer would be read.
when length >= 32768, the length would always be negative, and no data would be read.
When length < 32768 and (length % 256) >= 128, this bug would cause premature ending of the loop that is reading in data one character at a a time.
When length < 32768 and (length % 256) < 128, there would not be any obvious bug, and the complete buffer would be read.
when length >= 32768, the length would always be negative, and no data would be read.
>> len = bt[0] * 256 + bt[1];
There is no problem here. len is an integer and all the byte values are automatically promoted to integers.
There is no problem here. len is an integer and all the byte values are automatically promoted to integers.
>> all the byte values are automatically promoted to integers.
Due to the presence of the 256 integer literal.
Due to the presence of the 256 integer literal.
Yes, and they are promoted to integers in the range -128 to +127 because they are a signed data type.
Please just try it and see!
class testclass {
public static void main(String args[]) {
byte b = 140;
int i1, i2;
i1 = b;
i2 = b & 0xff;
System.out.println("i1 is " + i1 + ", i2 is " + i2 + "\n");
}
}
class testclass {
public static void main(String args[]) {
byte b = 140;
int i1, i2;
i1 = b;
i2 = b & 0xff;
System.out.println("i1 is " + i1 + ", i2 is " + i2 + "\n");
}
}
>> Yes, and they are promoted to integers in the range -128 to +127 because they are a signed data type.
You are absolutely right, I misinterpreted your post.
If you want to write the *START* message and the length of the whole message, please use DataInput- and DataOutputStreams. Another option is to send the *START* message and then a serialized String using an ObjectOutput- ObjectInputStream pair.
You are absolutely right, I misinterpreted your post.
If you want to write the *START* message and the length of the whole message, please use DataInput- and DataOutputStreams. Another option is to send the *START* message and then a serialized String using an ObjectOutput- ObjectInputStream pair.
ASKER
Now another question... How many times do I have to hit myself over the head before it starts hurting???
Ok, granted, the byte thing was stupid but in this particular code I am testing, the packets are all less than 128... although I could be wrong...
In any case, I'm going to test this first thing tomorrow morning when I get back to work...
Thanks for the input guys!
-- Bubba
ASKER
Ok, I fixed that particular bug but that didn't solve my problem. I did however re-write some of the code after looking at that byte thing and the DataOutput classes... And the bug went away.
Also, I verified that my packets were never larger than 90 or so bytes long in my test code although my final code will have to take the length more seriously.
-- Thanks again!
ASKER
Actually,
I also found this problem with the code:
int lenOut = response.length()+2;
out.write(lenOut / 256);
out.write(lenOut);
for (int j=0;j<response.length();j+ +)
out.write((byte)(response. charAt(j)) );
out.write(0); <---------------------- bug here
out.flush();
Notice that when the response is returned, a terminating null byte is added to the end of the output stream. So when I read the data, it gets out of phase by one byte... For instance, when reading the data, I read the length word, then the string which is exactly that size but then I assume that this is followed by the next length word (this is in the client code, not shown here). In any case, since the data does not comply with my protocol, I drop the data and wait for the next packet...
In my rewrite, I do not write out the null byte at the end.
-- Bubba
I also found this problem with the code:
int lenOut = response.length()+2;
out.write(lenOut / 256);
out.write(lenOut);
for (int j=0;j<response.length();j+
out.write((byte)(response.
out.write(0); <---------------------- bug here
out.flush();
Notice that when the response is returned, a terminating null byte is added to the end of the output stream. So when I read the data, it gets out of phase by one byte... For instance, when reading the data, I read the length word, then the string which is exactly that size but then I assume that this is followed by the next length word (this is in the client code, not shown here). In any case, since the data does not comply with my protocol, I drop the data and wait for the next packet...
In my rewrite, I do not write out the null byte at the end.
-- Bubba
=-)
http://www.vsj.co.uk/java/display.asp?id=13
R.K