I am using this code:
while (true) {
sendData("hi");
System.out.println("Data sent!");
BufferedReader inFromServer;
try {
inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
} catch (IOException e1) {
inFromServer = null;
e1.printStackTrace();
}
System.out.println("Recieved!"); //I see this de-bug message.
try {
modifiedSentence = inFromServer.readLine();
System.out.println("FROM SERVER: " + modifiedSentence); //I do NOT see this de-bug message!
} catch (IOException e) {
e.printStackTrace();
}
}
It successfully sends data to a server - And the server successfully sends data back:
public void run () {
//handle the session using the socket (example)
try {
sendData("Hi");
System.out.println("Data sent!"); //I see this de-bug message.
} catch (Exception e) {
e.printStackTrace();
}
}
However for some reason, the application seems to pause at the inFromServer.readLine() method. I see the "Recieved!" de-bug message, but not the "FROM SERVER" de-bug message.
There are no errors at all. It just seems to hang there.
Why is it hanging, and how can I fix that?
Well this simply means that inFromServer does not receive any line.
Make sure you really send a line,
Reads a line of text. A line is considered to be terminated by any one
of a line feed ('\n'), a carriage return ('\r'), or a carriage return
followed immediately by a linefeed.
Have a look at the readLine method :
String readLine(boolean ignoreLF) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
ensureOpen();
boolean omitLF = ignoreLF || skipLF;
bufferLoop:
for (;;) {
if (nextChar >= nChars)
fill();
if (nextChar >= nChars) { /* EOF */
if (s != null && s.length() > 0)
return s.toString();
else
return null;
}
boolean eol = false;
char c = 0;
int i;
/* Skip a leftover '\n', if necessary */
if (omitLF && (cb[nextChar] == '\n'))
nextChar++;
skipLF = false;
omitLF = false;
charLoop:
for (i = nextChar; i < nChars; i++) {
c = cb[i];
if ((c == '\n') || (c == '\r')) {
eol = true;
break charLoop;
}
}
startChar = nextChar;
nextChar = i;
if (eol) {
String str;
if (s == null) {
str = new String(cb, startChar, i - startChar);
} else {
s.append(cb, startChar, i - startChar);
str = s.toString();
}
nextChar++;
if (c == '\r') {
skipLF = true;
}
return str;
}
if (s == null)
s = new StringBuffer(defaultExpectedLineLength);
s.append(cb, startChar, i - startChar);
}
}
}
Note that this one receive a boolean, but calling readLine simply call this one with false passed, unless on Linux.
Notice the for(;;) loop, which is an infinite loop.
Try concatening to the "line" sent from the server
System.getProperty("line.separator");
Related
On a high level, we are using TCP to communicate between two clients on a network. The clients are operating under different languages.
Our messaging workflow is as follows:
C++ initiates a command
Java reads the command
Java does some simple logic
Java responds
We have started to see more and more discrepancies with what the C++ code is sending, and what the Java code is receiving.
In order to track down this error, we have placed multiple logging statements and a Wireshark profile to attempt to capture as much data as possible to track the message.
C++ logs show that the command is being sent as "123,abc,def,456"
Debugging the C++ shows that the byte order of the characters matches this, as the command to write to the socket is being fired.
Wireshark shows the message coming through as "123,abc,def,456"
Java reads from the socket, and shows that the message is jumbled. We have gotten messages such as:
"123,abc,def,456" (correct)
"bc,def,456"(truncated)
"1a2,3bdfec,4,56"(completely mangled)
Example of the C++ code
while ( Client->Connected && !bolExitNow){
data =S"";
Threading::Thread::Sleep(15);
bolReadStream = !bolReadStream;
if (!(bolReadStream && stream->DataAvailable )){
if (sharedInfo->CutSocketClientPort == RemotePort){
if (lbSocketMessages->read(&data)){ //the read() assigns stuff to data so that it's not an empty string anymore
bytes1 = Text::Encoding::ASCII->GetBytes( data);
stream->Write( bytes1, 0, bytes1->Length );
if (sharedInfo->curAcknowledgeItem->SendMessageType->CompareTo(data->Substring(7,2)) == 0){
sharedInfo->LastXXMsgTime = DateTime::Now ;
}
}
lbSocketMessages->acknowledge();
sharedInfo->WriteLog ( String::Format("{0} Sent msg: {1}",System::DateTime::Now.ToString("yyyyMMddHHmmss.fff"),data));//log write; This shows correct format message
}
}
continue;
}
Example of the java code
/** Shared read buffer. */
ConcurrentLinkedQueue<String> buffer = new ConcurrentLinkedQueue<String>();
//Instantiation
Socket client;
try{
client = new Socket(serverAddress, serverPort);
sock[thread] = new SocketMagic(client);
sock[thread].setMonitoring(false);
sock[thread].setHeartbeat("");
} catch (Exception e){
e.printStackTrace();
}
//Usage
while (!done){
if (socket[thread] != null && socket[thread].isAlive()){
message = socket[thread].getLine(MAX_DELAY_INTERVAL);
if(message!=null){
logger.log("RECEIVING ON {" + thread + "}: " + message);//displays incorrect message data
buffer.add(message);//Buffer for processing messages
}
}
//...
//logic
//...
if (buffer != null){
message = buffer.poll();
if (message != null){
response = processMessage(message,thread);//obviously wrong, as we read in incorrect information above.
}
}
}
SocketMagic library getline method is listed as
public String getLine()
{
return getLine(true, 0);//Always enable blocking
}
public String getLine(final boolean blocking, final int maxwait)
{
// to block, or not to block (while waiting for data)
StringBuilder buffer = new StringBuilder();
int character;
boolean messageStarted = false;
try
{
if (blocking)
{
int wait = 0;
while (maxwait <= 0 || wait < maxwait)
{
while (sockIn.ready())
{
character = sockIn.read();
if (character == STX)
{
if (!messageStarted)
{ // if no message started
messageStarted = true; // start a message
} else
{
buffer.setLength(0); // clear message buffer
}
continue; // don't add STX to buffer
}
// ignore characters prior to message start
if (!messageStarted)
{
continue;
}
// if not end of message, keep reading
if (character != ETX)
{
// append to buffer
buffer.append((char) character);
continue;
}
// if the message is a heartbeat, keep reading
if (buffer.toString().equals(heartbeat))
{
buffer.setLength(0); // clear buffer
messageStarted = false;
continue;
}
// we've got a complete message, return it
return buffer.toString();
}
// sleep loop to avoid CPU wasting
try
{
wait += SLEEPSTEP;
Thread.sleep(SLEEPSTEP);
if (monitor && (wait % (HEARTBEATINTERVAL)) == 0)
{
if (!sockOut.write(heartbeat))
{
return null;
}
}
} catch (InterruptedException ie)
{
return null;
}
} // ENDOF while ( !sock_in.ready() )
} // ENDOF if (blocking)
// set mark, if supported (which it should be)
if (sockIn.markSupported())
{
sockIn.mark(READAHEADSIZE);
}
while (sockIn.ready())
{
character = sockIn.read();
if (character == STX)
{
if (!messageStarted)
{ // if no message started
messageStarted = true; // start a message
} else
{
buffer.setLength(0); // clear message buffer
}
continue; // don't add STX to buffer
}
// ignore characters prior to message start
if (!messageStarted)
{
continue;
}
// if not end of message, keep reading
if (character != ETX)
{
buffer.append((char) character); // add char to buffer
continue;
}
// if we read a heartbeat message, keep reading
if (buffer.toString().equals(heartbeat))
{
// System.out.println("DEBUG: HEARTBEAT");
buffer.setLength(0);
messageStarted = false;
// set new mark position for input stream
if (sockIn.markSupported())
{
sockIn.mark(READAHEADSIZE);
}
continue;
}
// we've got a complete message, mission accomplished!
// return buffer.substring(1, buffer.length() - 1);
return buffer.toString();
} // ENDOF while (sockIn.ready())
// incomplete message, reset the mark, if supported
if (sockIn.markSupported())
{
sockIn.reset();
}
return null; // no message or incomplete message
} catch (IOException ioe)
{
return null;
}
} // ENDOF public String getLine(boolean blocking, int maxwait)
I am currently working on an add-on to a rhythm game called osu! using Java. There are multiple windows involved, but after the actionPerformed event listener is invoked for one of them, it creates another window that creates an object the constructor of which calls two methods that each use a BufferedReader. However, once I click the button for the actionPerformed, the program hangs and freezes until it is terminated from task manager. Here is the actionPerformed code for the GUI window:
private void btnCreateActionPerformed(ActionEvent evt) throws IOException {
String text = textBeats.getText();
if (text == null) {
JOptionPane.showMessageDialog(contentPane, "Please enter a positive number.");
}
boolean isNumber = true;
for (char c : text.toCharArray()) {
if (!Character.isDigit(c)) {
isNumber = false;
} else if (c == '-') {
isNumber = false;
}
}
if (isNumber) {
double beats = Double.parseDouble(text);
WindowCode window = new WindowCode(drawArea, file, beats);
window.setVisible(true);
this.dispose();
} else {
JOptionPane.showMessageDialog(contentPane, "Please enter a positive number.");
}
}
And here are the two methods called when creating WindowCode:
public double[] getLastTimingPoint() {
String line;
String timings[] = new String[8];
double pointElements[] = new double[8];
boolean isTiming = false;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(osuFile), "UTF-8"))){
while ((line = reader.readLine()) != null) {
if (line.contains("[TimingPoints]")) {
isTiming = true;
} else if (line.contains("[Colours]") || line.contains("[HitObjects]")) {
isTiming = false;
}
if (isTiming) {
if (!line.contains("[TimingPoints]") && !line.contains("[Colours]") && !line.contains("[HitObjects]") && line.length() > 0) {
timings = line.split(",");
}
}
}
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < timings.length; i++) {
pointElements[i] = Double.parseDouble(timings[i]);
}
System.out.println("1");
return pointElements;
}
public double[] getLastInheritedPoint() {
String line;
String timings[] = new String[8];
double pointElements[] = new double[8];
boolean isTiming = false;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(osuFile), "UTF-8"))) {
while ((line = reader.readLine()) != null) {
if (line.contains("[TimingPoints]")) {
isTiming = true;
}
while (isTiming) {
if (!line.contains("[TimingPoints]") && !line.contains("[Colours]") && !line.contains("-")) {
timings = line.split(",");
}
}
}
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < timings.length; i++) {
pointElements[i] = Double.parseDouble(timings[i]);
}
System.out.println("2");
return pointElements;
}
I have tried to print out checkpoint numbers and it only prints "1" to the console, leading me to believe that it is the second method that is causing this. My question is if the BufferedReader affects the EDT somehow and if it does, how I should get around it.
On the second method you have this inner loop:
while (isTiming) {
if (!line.contains("[TimingPoints]") && !line.contains("[Colours]") && !line.contains("-")) {
timings = line.split(",");
}
}
If the file being read contains this string "[TimingPoints]" then variable isTiming will be set to true, and no one else resets it back to false, being trapped into an infinite loop.
You should revise that loop logic.
I have two methods, both using FileInputStream Objects.
The First one returns expected value. This method works fine.
But the Second method returns nothing. The value passed to the second method is not null.
I need to get the hexadecimal format of the files passed to methods.
Why is it so? Kindly Explain.
Here is my code
public String binaryFile1(File file1){
try{
stringBuilder1=new StringBuilder();
is1=new FileInputStream(file1);
while(b!=-1){
counter++;
b=is1.read();
String s = Integer.toHexString(b).toUpperCase();
if (s.length() == 1) {
stringBuilder1.append('0');
}
if(counter%5==0){
stringBuilder1.append(s).append("\n");
counter=0;
}else
stringBuilder1.append(s).append(' ');
}
is1.close();
}catch(Exception e){
e.printStackTrace();
}
return stringBuilder1.toString();
}
public String binaryFile2(File file2){
try{
stringBuilder2=new StringBuilder();
is2=new FileInputStream(file2);
while(b!=-1){
counter++;
b=is2.read(); //Here b does not get any content assigned.
String s = Integer.toHexString(b).toUpperCase();
if (s.length() == 1) {
stringBuilder2.append('0');
}
if(counter%5==0){
stringBuilder2.append(s).append("\n");
counter=0;
}else
stringBuilder2.append(s).append(' ');
}
is2.close();
}catch(Exception e){
e.printStackTrace();
}
return stringBuilder2.toString(); //Here stringBuilder2 is null
}
Since b is shared and you don't reset it after binaryFile1 it's still -1 at the start of binaryFile2. I suggest you use,
int b;
while ((b = is2.read()) != -1) {
// ...
}
Edit
It is important to close your resources when you're done. I also suggest you try and limit variable scope as much as possible. Using try-with-resources you could write binaryFile2 like
public String binaryFile2(File file) {
StringBuilder sb = new StringBuilder();
int counter = 0;
try (InputStream is = new FileInputStream(file)) {
int b;
while ((b = is.read()) != -1) {
counter++;
String s = Integer.toHexString(b).toUpperCase();
if (s.length() == 1) {
sb.append('0');
}
sb.append(s);
if (counter % 5 == 0) {
sb.append(System.lineSeparator());
counter = 0;
} else {
sb.append(' ');
}
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
I've got a simple socket server (it is for HL7 communication). When it runs longer in production, socket threads hang and consume a lot of CPU time.
This is the relevant code (shortened) for the listener thread:
public void run() {
try {
serverSocket = new ServerSocket(port, backlog, bindAddress);
serverSocket.setSoTimeout(timeout); // 1000 ms
do {
Socket socket = null;
try {
socket = serverSocket.accept();
} catch (SocketTimeoutException to) {
socket = null;
} catch (InterruptedIOException io) {
socket = null;
} catch (IOException e) {
logger.fatal("IO exception while socket accept", e);
socket = null;
}
try {
if (socket != null)
processConnection(socket);
} catch (RuntimeException e) {
logger.fatal("caught RuntimeException trying to terminate listener thread", e);
}
} while (running);
} catch (IOException e) {
logger.fatal("error binding server socket - listener thread stopped", e);
}
}
This code starts a new thread for processing an incoming connection:
protected void processConnection(Socket socket) {
Hl7RequestHandler requestHandler = createRequestHandler();
requestHandler.setSocket(socket);
requestHandler.start();
}
This is the code for the request handler thread (keepAlive is set to true):
public void run() {
try {
setName("Hl7RequestHandler-" + socket.getPort());
processRequest();
} catch (IOException e) {
logger.fatal("IO exception during socket communication", e);
}
}
public void processRequest()
throws IOException {
socket.setSoTimeout(socketTimeout); // 1000 ms
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
BufferedReader inputReader = new BufferedReader(new InputStreamReader(inputStream, encoding));
Writer outputWriter = new OutputStreamWriter(outputStream, encoding);
int timeouts = 0;
boolean failure = false;
do {
StringBuilder message = new StringBuilder();
try {
char c;
do {
c = (char)inputReader.read();
if ((c == CARRIAGE_RETURN || c == START_OF_MESSAGE) &&
message.length() == 0)
else if (c != END_OF_MESSAGE && ((short)c) != -1)
// ein Byte "Nutzlast"
message.append(c);
} while (c != END_OF_MESSAGE && ((short)c) != -1);
} catch (SocketTimeoutException te) {
timeouts++;
if(!keepAlive && timeouts >= 3 ) {
socket.close();
return;
}
}
String messageStr = message.toString();
if (messageStr.length() == 0)
continue;
failure = !processMessage(messageStr, outputWriter);
outputWriter.flush();
outputStream.flush();
// nächste Runde?
if (!keepAlive || failure)
socket.close();
} while (keepAlive && !failure);
}
When I test this locally, it works well.
But in production, there are multiple request handler threads that "hang". "Keep Alive" is ment to hold open the connection waiting for more messages. (To avoid opening up new connections all the time.) I assume inputReader.read() returns -1 after the timeout of 1s, which results in calling the method just again. Why does this eat up all the CPU time?
Have you got any advice?
Thanks in advance,
Matthias
One thing I can see straight off is this :
char c;
do {
c = (char)inputReader.read();
if ((c == CARRIAGE_RETURN || c == START_OF_MESSAGE) &&
message.length() == 0)
else if (c != END_OF_MESSAGE && ((short)c) != -1)
// ein Byte "Nutzlast"
message.append(c);
} while (c != END_OF_MESSAGE && ((short)c) != -1);
is the cast of the inputReader.read() to char. BufferedReader.read() returns an int, a signed value. You cast it to char that is an unsigned value, discarding the negative sign if there is one, a narrowing conversion. Then converting to short is not bringing back the negative sign if there was one.
Try rewriting as :
char c;
int val;
do {
val = inputReader.read();
// do this if you want, you don't have to
c = (char) val;
if ((c == CARRIAGE_RETURN || c == START_OF_MESSAGE) &&
message.length() == 0)
else if (c != END_OF_MESSAGE && ((short)c) != -1)
// ein Byte "Nutzlast"
message.append(c);
} while (c != END_OF_MESSAGE && val != -1);
I've taken another look at your loop and I'm confused.
char c;
do {
c = (char)inputReader.read();
if ((c == CARRIAGE_RETURN || c == START_OF_MESSAGE) &&
message.length() == 0)
else if (c != END_OF_MESSAGE && ((short)c) != -1)
// ein Byte "Nutzlast"
message.append(c);
} while (c != END_OF_MESSAGE && ((short)c) != -1);
The logic of your if statements are confusing (to me at least).
You have no statements for the first if clause, not even an empty statement.
You have to have either {} or a ; Does your code compile?
I'm having some issues with a while loop. This while loop is run in a thread, and is the "main loop" of the thread, and I'm having issues with it not continuing if one of the if statements it loops over is false. This thread handles both sending and receiving IRC Commands/Messages for use in a minecraft client.
The code as it stands is below:
do {
System.out.println("IRC Thread Looped!");
if(tosend != "") {
writer.write("PRIVMSG " + channel + " :"+tosend+"\r\n");
System.out.println(tosend);
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] \2477"+nick+": \247f"+tosend);
tosend = "";
writer.flush();
}
if((line = reader.readLine()) != null) {
if(line.startsWith("PING ")) {
writer.write("PONG " + line.substring(5) + "\r\n");
writer.flush( );
}
else {
// we need to pretty this ugly sh*t up!
try {
String parsedline;
String args[] = line.split("!");
String args2[] = args[1].split(":");
args[0] = args[0].substring(1, args[0].length());
parsedline = "\2477"+ args[0] +": \247f"+ args2[1];
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] "+parsedline);
}
catch(Exception e) {
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f]\247f "+line);
continue;
}
}
}
try {
Thread.sleep(90L);}catch(Exception e) { };
}
} while(true);
Note that java threads like to eat exceptions that get thrown out of the run() method.
Since you have IO such as if((line = reader.readLine()) != null){ not in a try/catch, you might be throwing an exception and exiting.
What I like to do with threads is to put the main thread code in runImpl() and have the run() look like this.
public void run()
{
try
{
runImpl();
}
catch( Throwable t )
{
// log the throwable
}
}
Then at a minimum you can discover that your thread threw something unexpected.
If the problem is caused by getLine() blocking behavior you could probably fix it this way. I haven't run that code so I don't guarantee it will work. Also make sure that reader is a BufferedReader.
StringBuilder sb = new StringBuilder();
String line = null;
int n = 0;
do {
System.out.println("IRC Thread Looped!");
if(tosend != ""){
writer.write("PRIVMSG " + channel + " :"+tosend+"\r\n");
System.out.println(tosend);
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] \2477"+nick+": \247f"+tosend);
tosend = "";
writer.flush();
}
while (reader.ready()) {
int c = reader.read();
if (c == -1) {
if (n > 0) {
line = sb.toString();
sb = new StringBuilder();
}
break;
}
if (c == '\n' || c == '\r') {
line = sb.toString();
sb = new StringBuilder();
break;
}
sb.append((char)c);
n++;
}
if(line != null){
if (line.startsWith("PING ")) {
writer.write("PONG " + line.substring(5) + "\r\n");
writer.flush( );
}
else
{
//we need to pretty this ugly shit up!
try{
String parsedline;
String args[] = line.split("!");
String args2[] = args[1].split(":");
args[0] = args[0].substring(1, args[0].length());
parsedline = "\2477"+args[0] +": \247f"+ args2[1];
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f] "+parsedline);
}catch(Exception e){
mc.thePlayer.addChatMessage("\247f[\247bIRC\247f]\247f "+line);
continue;
}
}
line = null;
n = 0;
}
try{Thread.sleep(90L);}catch(Exception e){};
} while(true);