It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I am new to socket programming, and have a piece of code which opens a socket and writes into it. I set the timeout for the socket as one minute, and want to close the socket and exit after I reach a certain condition.
My code is not closing the socket when the condition is met:
#Override
public void run() {
Socket socket =null;
PrintWriter writer = null;
BufferedReader reader = null;
String host = ServiceProperties.getInstance().getControllerHost();
String port = "1234;
String info="";
// TODO Auto-generated method stub
try {
socket = new Socket(host, Integer.valueOf(port));
socket.setSoTimeout(60000);
writer = new PrintWriter(socket.getOutputStream(), true);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
SampleBean sBean = (SampleBean) (FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("sampleBean"));
info = ControllerDAO.getInstance().getControllerAndTimeScheduleInfo(sBean.getId());
writer.println("set TimeSchedule "+ info +" value ["+str+"]");
}
catch(UnknownHostException ex) {
ex.printStackTrace();
}
catch(IOException ex) {
ex.printStackTrace();
}
String line="";
try {
System.out.println("BEFORE WHILE");
System.out.println(new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()));
while((line= reader.readLine())!=null ) {
System.out.println(line);
if(line.contains("OK")){
System.out.println("line contains OK ");
break;
}
try {
Thread.sleep(5000);
}
catch(InterruptedException ex) {
ex.printStackTrace();
}
}
System.out.println("AFTER WHILE");
System.out.println(new SimpleDateFormat("HH:mm:ss").format(Calendar.getInstance().getTime()));
}
catch(IOException ex) {
ex.printStackTrace();
}
try {
writer.close();
reader.close();
socket.close();
}
catch(IOException ex) {
ex.printStackTrace();
}
}
});
thread.run();
Output:
//"BEFORE WHILE"
// 14:54:55
// prints line
// //prints empty line
// now it waits for like 40 seconds
// line contains OK //condition met here
// breakoutof the loop
// "AFTER WHILE"
// 14:55:55
Why is it waiting on the third iteration? The third iteration is when the condition is met, after waiting for about 40 seconds.
What am I doing wrong?
You need to catch a SocketTimeoutException (see the doc) if your request times out and then close the socket in that catch, as the socket stays valid even if there is a time out.
There are a few problems here, but I think the main one is that you are not closing the socket properly. This should be in the finally block of the try block that encapsulates the sockets, NOT in its own try block.
SO_TIMEOUT does not affect close(), try setting SO_LINGER.
Related
This question already has answers here:
How to interrupt BufferedReader's readLine
(10 answers)
How to properly stop the Thread in Java?
(9 answers)
Closed 4 years ago.
I am trying to terminate the child thread, that's waiting for the input from the server. I've tried to do it with the flag, but it stops on the
message = serverReader.readLine() && !isClosed(),
because it waits for the input from the server and only after this input it checks the flag and interrupts. But it's not a good solution, cause i couldn't stop it without server message.
I also tried to check firstly the flag and then readline(), but it doesn't work too.
Is it any good solutions for that?
#Override
public void run() {
String message;
try {
while((message = serverReader.readLine()) != null && !isClosed()) {
consoleWriter.println("Other user: " + message);
consoleWriter.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void setUpNetworking() {
try {
Socket socket = new Socket("127.0.0.1", 5000);
InputStreamReader streamReader = new InputStreamReader(socket.getInputStream());
serverWriter = new PrintWriter(socket.getOutputStream());
serverReader = new BufferedReader(streamReader);
//Starting listening messages from server
incomeReader = new Thread(new IncomeMessagesReader(serverReader, consoleWriter, this));
incomeReader.start();
System.out.println("Networking established");
} catch (IOException e) {
e.printStackTrace();
}
}
Swap the && order. The && operator is short-circuit, so the right side won't execute if the left side fails. The opposite is true for ||.
while (!isClosed() && readLine())
I have a buffered reader reading from a socket line by line. So this works fine. However this looks pretty low level to me and a telnet client is not able to close the connection sending a ctrl + c. So I am wondering if there is some nicer implementation of a stream reader? I.e. the whole tread and loop could easily be abstracted away and just call lambda functions on read, close and error. Or what is the best practice here?
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
new Thread(() -> {
while (true) {
try {
String readLine = bufferedReader.readLine();
// if readline is null then the client just closed connection
// if there is something in the buffer and the clients close the connection
// raadLine returns with anything left in the buffer up until the client left
// and returns a second time with null
if (readLine == null) {
logger.info("client closed connection");
socket.close();
disconnectAll();
break;
} else {
for (Listener listener : listeners) {
listener.messageReceived(this, readLine);
}
}
} catch (IOException | IllegalAccessException | InvocationTargetException e) {
logger.error(e.getMessage(), e);
try {
socket.close();
} catch (IOException e1) {
logger.error(e1.getMessage(), e1);
} finally {
disconnectAll();
break;
}
}
}
}).start();
I think your base problem is that sending Ctrl-C doesn't close a stream, Ctrl-D does. Edit: Ctrl-Z on Windows.
The remainder of the question really belongs to https://codereview.stackexchange.com/, but here goes.
Firstly, you are closing a socket that was opened outside.
Secondly, you shouldn't create Thread objects, but use an ExecutorService.
Third, I'd recommend using try-with-resource to ensure everything closes automatically.
Fourth, you can use the read line in your while statement instead of using while(true) - break.
This gives you something like
ExecutorService readerExecutor = Executors.newSingleThreadExecutor();
public startReadingSocket(Supplier<Socket> createSocket, Consumer<String> lineHandler, Consumer<Exception> excHandler, Runnable cleanUp) {
readerExecutor.submit(() -> {
String readLine;
try (Socket s = createSocket.get();
InputStreamReader isReader = new InputStreamReader(s.getInputStream());
BufferedReader reader = new BufferedReader(isReader)) {
while (readLine = reader.readLine() != null) {
lineHandler.accept(readLine);
}
System.out.println("client closed connection.");
} catch (Exception e) {
excHandler.accept(e);
} finally {
cleanUp.run();
}
}
}
And you can run that via
startReadingSocket(() -> new Socket(host, port),
line -> listeners.forEach(l -> l.messageReceived(this, line)),
ex -> logger.error(ex.getMessage, ex),
this::disconnectAll);
Now this is Java 8, with previous versions you'd need to create interfaces and anonymous classes for the lambdas.
This question already has an answer here:
Java networking, really strange error
(1 answer)
Closed 8 years ago.
Im working on a little chat program and now i have a huge problem and i can not solve it.
I dont know where the mistake could be, for me the code is right. So i really really need help. I have 2 threads in my server, 1 thread for accepting clients and the other for the streams. And the thread for the streams is not working right. It sends only 1 time a message back to the client and multiple clients are also not working. And there is another strange problem. I can only send 1 message back, if i put the JOptionPane-message called "Sockets empty" in the else statement, without it doesnt work.
Here is the stream thread code:
private static Runnable streamThread = new Runnable()
{
public void run()
{
while(true)
{
if(!(socketList.isEmpty()))
{
for(int i = 0; i < socketList.size(); i++)
{
try
{
String key = socketList.get(i);
if(socketHashMap.containsKey(key))
{
Socket connection = socketHashMap.get(key);
ObjectInputStream ois = new ObjectInputStream(connection.getInputStream());
String response = (String) ois.readObject();
ObjectOutputStream oos = new ObjectOutputStream(connection.getOutputStream());
oos.writeObject(key + ": " + response);
oos.flush();
}
if(connection.isClosed())
{
JOptionPane.showMessageDialog(null, "Client closed connection", "Info", JOptionPane.INFORMATION_MESSAGE);
}
}
catch (IOException | ClassNotFoundException e) {
JOptionPane.showMessageDialog(null, "ERROR: " + e.getMessage(), "ALARM", JOptionPane.ERROR_MESSAGE);
try {
connection.close();
connection.shutdownInput();
connection.shutdownOutput();
listClientsModel.remove(i);
} catch (IOException e1) {
}
}
}
}
else
{
JOptionPane.showMessageDialog(null, "SOCKETS LEER", "Info", JOptionPane.INFORMATION_MESSAGE);
}
}
}
};
And if you want to see the complete servercode :
http://pastebin.com/sxGGRnJv
The documentation for getOutputStream says:
Closing the returned OutputStream will close the associated socket.
And that is the problem. You create an ObjectOutputStream, but don't keep a reference to that object around. As this object gets garbage collected, it will call close() which will close the socket's output stream.
Same problem with the InputStream.
You could, for example, create a class that contains your socket and input and output stream and store that in your map instead of just the socket. That way you can re-use the streams.
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Well I have this problem and I dont know whats wrong with the codeing,
catch (FilenotFoundException e){
system.out.println("File not found");
}
try
{
FileReader freader = new FileReader("MyFile.txt");
}
}
Its asking for what the error is?? I thought it may be the e not being capitalized is that the reason?
A try{} block should be followed by a catch{} block or finally{} block, you have reversed it.
Use like this: -
try {
FileReader freader = new FileReader("MyFile.txt");
} catch (FileNotFoundException e){
System.out.println("File not found");
}
As per Java Naming Convention: -
Class Names start with a capital letter, and all subsequent word also start with capital letter. So, FilenotFoundException should be FileNotFoundException
And, system should be -> System.
A catch{} block follows a try{} block, not the other way around.
Also, FilenotFoundException should be FileNotFoundException. I doubt it will compile with the alternate spelling. Likewise with system vs. System, as indicated in #Rohit Jain's answer.
It should be otherway. try followed by catch.
try
{
FileReader freader = new FileReader("MyFile.txt");
}catch (FileNotFoundException e){
System.out.println("File not found");
}
Since Java 7:
try( FileReader freader = new FileReader("MyFile.txt"))
{
use freader
}// try
catch( IOException e)
{
e.printStackTrace();
}
catch block should follow try
try {
//code that exception might occur
}
catch(Exception ex) {
//catch the exception here.
}
your try block should either be followed by catch or finally.
try {
//code that exception might occur
}
finally {
//close your resources here
}
I have 2 sockets and I am using BufferedReader around it's InputStreams. What I am trying to do is take all input from the first socket and send it to the other socket (and visa versa).
The problem is that if the first one does not send a message, it will still block on the first readLine() even though the 2nd socket has already sent some data and is ready. I would like to continue with this simple approach of using no additional threads.
Here's some code that I wrote up, as you can see I have 2 BufferedReaders (in0 and in1) , the program gets stuck at in0.readLine() (blocking).
private void network()
{
PrintWriter out0 = null, out1 = null;
BufferedReader in0 = null,in1 = null;
try{
//clients[] is an array of Socket[2]
in0 = new BufferedReader(new InputStreamReader(clients[0].getInputStream()));
out0 = new PrintWriter(clients[0].getOutputStream(), true);
in1 = new BufferedReader(new InputStreamReader(clients[1].getInputStream()));
out1 = new PrintWriter(clients[1].getOutputStream(), true);
} catch (IOException e) {
System.out.println("Accept failed: 4445");
System.exit(-1);
}
int count = 1;
while(true)
{
System.out.println("network check loop # " + count);
++count;
String nextMessage = null;
try {
if( (nextMessage = in0.readLine()) != null)
{
this.relayMessage(nextMessage,out1);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Middle of network check loop");
nextMessage = null;
try {
if((nextMessage = in1.readLine()) != null)
{
this.relayMessage(nextMessage,out0);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
How can I just skip that statement if in0 is not ready to give me some data? I have seen BufferedReader's ready() method and have attempted to use in0.ready() && readLine() but this causes an infinite loop as neither of the bufferedreaders appear to ever be 'ready'. As well, I am certain that the messages being sent over the socket end in newline characters so readLine() should process correctly!
Any ideas?
Try to use setSoTimeout to put a timeout on your read(), then you just need to catch the SocketTimeoutException if the timer has expired.
Here break and continue keywords are your friends.
The simplest approach is to use two threads. This way you don't have to write your own scheduling code to determine which thread should be running. BTW: The code to copy from one socket to another is the same in each thread, reducing duplication.
To manage your threads I would use an ExecutorService which will make shutting downt eh threads easier.