This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
java timer and socket problem
So here is the code.
What I want to do - is client loop with server, to get messages from server, which sends them sometimes.
Here is attempt with timer.
private MessageFrame mf;
private User us;
private Contact cn;
private Socket s;
private PrintStream ps;
private BufferedReader br;
private Timer timer ;
public MessageFrameListener(MessageFrame m_f, User u_s, Contact c_n){
timer = new Timer(500,new timerListener());
mf = m_f;
us = u_s;
cn = c_n;
m_f.addButtonListener(new SButtonListener());
m_f.addWinListener(new FrameListener());
}
public void init(){
try {
s = new Socket(InetAddress.getLocalHost(), 8072);
ps = new PrintStream(s.getOutputStream());
br = new BufferedReader( new InputStreamReader(s.getInputStream()));
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
timer.start();
}
public class timerListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
//String insert = mf.getInput();
String result;
try {
//проверить, что буфер не пуст
if((result = br.readLine()) != null){
String[] results = result.split(" ");
if("m".equals(results[0])){
if("-1".equals(results[2]))
mf.addLine2("Error");
else{
mf.addLine2(results[3]);
}
}
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
But when I run it - the program stops reacting to my actions.
I can't write a text, or press a button.
Read calls to BufferedReader are blocking, Run them in a separate thread preferably a swing worker. Your readLine() call is causing the main event thread to hang which means no other events are propagating.
To confirm this put a break in the TimerActionListener and investigate the running thread stack or just SIGQUIT and thread dump. It should be pretty clear what thread the read call is causing to block.
I believe your br.readline() call blocks until you get data from your InputStream. If nothing is coming over the socket to read, the code will just hang there.
You may want to see the thread over here: Asynchronous IO in Java?
Related
I am writing a Java client/server GUI application using sockets and here is the problem:
I have a button to start listening for a specified port:
button actionPerformed method
private void listenButtonActionPerformed(java.awt.event.ActionEvent evt) {
int port = Integer.parseInt(portTextfield.getText(), 10);
try {
socket.listen(port);
} catch (IOException ex) {
}
}
Here is the socket.listen method
public static void listen() throws IOException {
ServerSocket ss = new ServerSocket(port);
while (true)
new socket(ss.accept());
}
"socket" class extends "Thread"
So after ss.accept() returns a value it creates new socket instance in separate thread.
After clicking the button the GUI freezes because inside the socket.listen method there is an infinite loop. How can I avoid that?
You have two pitfalls in your design:
ss.accept() is a blocking call so your UI will freeze until there is an incoming connection
Never run while(true) loops in the EDT.
Instead do the following:
When the button is clicked create a thread that will start listening for incoming connections.
Whenever you have an incoming connection, create another thread that will take the incoming client connection and deal with it.
as long as your
new socket(ss.accept());
returns immediately, you only need to change your
while (true)
this puts the EDT (Event Dispatch Thread) into an infinite loop and your GUI becomes irresponsive. So, delete this line.
If you can't then use the SwingWorker class ( http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html#process(java.util.List)
Create a nested class that extents SwingWorker. Just call a swingWoker.execute(); (after you have created its object) in your listenButtonActionPerformed(java.awt.event.ActionEvent evt) method.
See the tutorial: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
Never create a new thread and run it from from the Swing EDT
Check this out: http://javarevisited.blogspot.ro/2012/02/what-is-blocking-methods-in-java-and.html
1) If you are writing GUI application may be in Swing never call
blocking method in Event dispatcher thread or in the event handler.
for example if you are reading a file or opening a network connection
when a button is clicked don't do that on actionPerformed() method,
instead just create another worker thread to do that job and return
from actionPerformed(). this will keep your GUI responsive, but again
it depends upon design if the operation is something which requires
user to wait than consider using invokeAndWait() for synchronous
update.
Using multiple threads: http://javarevisited.blogspot.ro/2011/02/how-to-implement-thread-in-java.html
You will need to use Multi-Threading. If I where you, I would separate the GUI code and the server code and when the button is pressed, I simply launch the Server code as a new Thread.
Your code is freezing the GUI basically because all events are executed on the Event Dispatcher Thread (EDT) which is the thread which takes care of all your GUI stuff and respective events. If you either block it, stop it or throw in loops it will affect on its performance.
Try these...
1. During getting the initial connection delay can occur, so first create and empty socket,then try to connect to the server.
`Socket s = new Socket();`
`s.connect(new InetSocketAddress("ip_addr",port_nos),1000);`
2. And Secondly always keep the Non-UI work out of Your UI thread..
Here is my Example of Server - Client Communication..
Client side code:
public class ClientWala {
public static void main(String[] args) throws Exception{
Boolean b = true;
Socket s = new Socket();
s.connect(new InetSocketAddress("127.0.0.1", 4444),1000);
System.out.println("connected: "+s.isConnected());
OutputStream output = s.getOutputStream();
PrintWriter pw = new PrintWriter(output,true);
// to write data to server
while(b){
if (!b){
System.exit(0);
}
else {
pw.write(new Scanner(System.in).nextLine());
}
}
// to read data from server
InputStream input = s.getInputStream();
InputStreamReader isr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(isr);
String data = null;
while ((data = br.readLine())!=null){
// Print it using sysout, or do whatever you want with the incoming data from server
}
}
}
Server side code:
import java.io.*
import java.net.*;
public class ServerTest {
ServerSocket s;
public void go() {
try {
s = new ServerSocket(44457);
while (true) {
Socket incoming = s.accept();
Thread t = new Thread(new MyCon(incoming));
t.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
class MyCon implements Runnable {
Socket incoming;
public MyCon(Socket incoming) {
this.incoming = incoming;
}
#Override
public void run() {
try {
PrintWriter pw = new PrintWriter(incoming.getOutputStream(),
true);
InputStreamReader isr = new InputStreamReader(
incoming.getInputStream());
BufferedReader br = new BufferedReader(isr);
String inp = null;
boolean isDone = true;
System.out.println("TYPE : BYE");
System.out.println();
while (isDone && ((inp = br.readLine()) != null)) {
System.out.println(inp);
if (inp.trim().equals("BYE")) {
System.out
.println("THANKS FOR CONNECTING...Bye for now");
isDone = false;
s.close();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
try {
s.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new ServerTest().go();
}
}
I have a small bit of code that runs in an applet that contains SWING controls and is used to write information to a socket on a certain port and then listens for a response. This works fine, but there is a problem with it. The port listener is essentially in a loop until null is received by the server. I want users to be able to perform other actions in the GUI instantiated by the applet while waiting for the server to respond (this could take minutes to occur). I also need to worry about the connection between the server and the client disconnecting. But the way the code is written, the applet appears to freeze (its really in a loop) until the server responds. How can I allow the listener to do its listening in the background, allowing other things to occur in the program. I assume I need to use threads and I'm sure for this application, it is easy to implement, but my lack of a solid thread foundation is hampering me. Below is the code (you can see how simple it is). How can I improve it to make it do what I need it to do>
public String writePacket(String packet) {
/* This method writes the packet to the port - established earlier */
System.out.println("writing out this packet->"+packet+"<-");
out.println(packet);
String thePacket = readPacket(); //where the port listener is invoked.
return thePacket;
}
private String readPacket() {
String thePacket ="";
String fromServer="";
//Below is the loop that freezes everything.
try {
while ((fromServer = in.readLine()) != null) {
if (thePacket.equals("")) thePacket = fromServer;
else
thePacket = thePacket+newLine+fromServer;
}
return thePacket; //when this happens, all listening should stop.
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
Thanks,
Elliott
There lots of different means of getting the IO performed on a different thread, but in this case you probably want to use SwingWorker.
Your code would look something like:
private final Executor executor = Executors.newSingleThreadExecutor();
public void writePacket(final String packet)
{
// schedules execution on the single thread of the executor (so only one background operation can happen at once)
//
executor.execute(new SwingWorker<String, Void>()
{
#Override
protected String doInBackground() throws Exception
{
// called on a background thread
/* This method writes the packet to the port - established earlier */
System.out.println("writing out this packet->"+packet+"<-");
System.out.println(packet);
String thePacket = readPacket(); //where the port listener is invoked.
return thePacket;
}
#Override
protected void done()
{
// called on the Swing event dispatch thread
try
{
final String thePacket = get();
// update GUI with 'thePacket'
}
catch (final InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (final ExecutionException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
private String readPacket()
{
String thePacket ="";
String fromServer="";
//Below is the loop that freezes everything.
try
{
while ((fromServer = in.readLine()) != null)
{
if (thePacket.equals(""))
thePacket = fromServer;
else
thePacket = thePacket+newLine+fromServer;
}
return thePacket; //when this happens, all listening should stop.
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
All the network I/O should be in a separate thread.
BTW readLine() returns null when the server closes the connection, not when it has finished sending data for the moment.
I have to build a chat program.
There is the server class, the client class and two threads to write and receive messages.
the two threads should run in an infinite loop and check all the time if there is an input and print that input afterwards.
But my program works for just one round. So the server and the client can write one single message, afterwards it stops and does not check for another message. Why does the thread not start again from the begin when it's never interrupted? --> see the code beneath
I hope you know what my problem is, it's quite hard for me to describe.
Thread to read a new Message
public class MsgWriter extends Thread {
private Socket s;
public MsgWriter(Socket s){
this.s = s;
}
public void run(){
int i = 0;
OutputStream out = null;
PrintWriter writer;
Scanner input;
while(!interrupted()){
try{
synchronized(s){
input = new Scanner (System.in);
out = s.getOutputStream();
writer = new PrintWriter(out);
String toserver = input.nextLine();
writer.write(toserver);
writer.flush();
System.out.println("me: " + toserver);
}
try {
Thread.sleep((int) (100 * Math.random()));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}catch(Exception e) {
}
}
}
}
Thread to check if there is a new message and prints it.
public class MsgReader extends Thread {
Socket s;
public MsgReader(Socket s){
this.s = s;
}
public void run() {
int i = 0;
while (!interrupted()) {
try{
synchronized(s){
InputStream in = s.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String s = null;
while((s=reader.readLine()) != null){
System.out.println("d");
}
}
try {
Thread.sleep((int) (100 * 1));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}catch (Exception e){
}
}
}
}
The Server class starts a new server and waits for a client, afterwards it starts the two threads. The same with the client class, it connects to the server and starts the threads.
You're probably thowing an exception somewhere. In your catch blocks, print the error.
try {
} catch (Exception e) {
System.out.println("Error: " + e);
}
I am working on a small project where I have to communicate to an Android app on my phone and with Arduino.
Now, I have the connection between Android and laptop (used as server, I have a small amount of data stored here), and I can change the contents of text files when I send certain instructions from Android app.
This is how I do it:
I have a ServerSide class that listens on port 3000 and I read the text I stream from phone, then I make certain changes in text files for different messages.
The code:
public class ServerSide {
public static void main(String[] args) throws IOException {
while (true) {
ServerSocket serverSocket = null;
// check if client is trying to connect
try {
serverSocket = new ServerSocket(3000);
} catch (IOException e) {
System.err.println("Cannot communicate on this port");
System.exit(1);
}
Socket clientSocket = null;
// move to another socket
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed");
System.exit(1);
}
// stream that will be sent to client. "true" is for creating from
// existing
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
true);
// stream that comes from the client
BufferedReader in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
String recivedData, sendData;
ServerProtocol communicationProtocol = new ServerProtocol();
while ((recivedData = in.readLine()) != null) {
sendData = communicationProtocol.process(recivedData);
out.println(sendData);
System.out.println("The text should now be written in file");
System.out.println(sendData);
}
in.close();
out.close();
clientSocket.close();
serverSocket.close();
}
}
}
ServerProtocol.process() is the method that updates the files
By the way, this is a good version of a program that implies connection via sockets (if anyone should need information about this, at a future time).
Everything works great, I can see my updates immediatly after I send them, the server is up and running, waiting for messages.
I forgot to mention, I am new to java and a novice in programming, in general.
Now, I want this code I managed to write to be part of a bigger "server". By "server", I understand a program that "serves", performs a service. When it runs on my laptop, it takes information that comes from the Internet on the port I specify, change things in files according to my messages, keeps theese files updated and in the same time it uses theese files to "interpert" data I send from phone, and then sends according messages to Arduino Shield. (THIS IS WHAT I WANT TO ACHIVE)
I guess that what I miss, is the following:
How do i make this code I have written untill now, part of a bigger project, that does all that?
I managed to split the project in 3 parts:
Communication laptop - Android
Constant data updates
Communication laptop - Arduino
I've done some research, and I came across threads. So I thought about having the communication with Android on a separate thread of a MainServer. I clearly got it wrong, because it doesn't do what I expect it to do, so here is the code:
I create the ServerSide class that extends Thread, and has a run() method that should be called when I start the thread. It behaves just like the one above, but the executing code lays inside a run() method:
public class ServerSide extends Thread {
#Override
public void run() {
while (true) {
ServerSocket serverSocket = null;
// check if client is trying to connect
try {
serverSocket = new ServerSocket(3000);
} catch (IOException e) {
System.err.println("Cannot communicate on this port");
System.exit(1);
}
Socket clientSocket = null;
// move to another socket
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed");
System.exit(1);
}
// stream that will be sent to client. "true" is for creating from
// existing
PrintWriter out = null;
try {
out = new PrintWriter(clientSocket.getOutputStream(), true);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// stream that comes from the client
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
clientSocket.getInputStream()));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String recivedData, sendData;
recivedData = null;
sendData = null;
ServerProtocol communicationProtocol = new ServerProtocol();
try {
while ((recivedData = in.readLine()) != null) {
try {
sendData = communicationProtocol.process(recivedData);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.println(sendData);
System.out
.println("The text should now be written in file");
System.out.println(sendData);
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.close();
try {
clientSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Then, I have the MainServer:
public class MainServer {
public static void main(String[] args) throws IOException {
System.out.println("Started");
Thread myThread = new Thread(new ServerSide());
myThread.start();
System.out.println("Started2");
while (true);
}
}
It should do nothing, just start the new thread. I expect this new thread do act just like the old ServerSide above (the one with main() method).
Someone, please tell me where I got it wrong !?!
Well, two things seem a little unusual about the MainServer class. First, creating a thread with new Thread(new ServerSide()) will cause a compilation error. There are two ways to fix this: either you make ServerSide implement the Runnable interface instead of extending Thread, or you create the thread with new ServerSide(). Second, the infinite loop at the end of main is useless and can be removed. The main method runs in its own thread, and if it finishes, all other threads keep running, and there is no need to keep main alive. The program will indeed keep running when main finishes, which may seem strange, but that's what will happen.
Everything was OK here, my problem was actually my phone connection to wi-fi, I was a bit too far in the back yard :)
I am trying to create a UDP listener that will listen on a separate thread. It works fine the first time but when I stop the connection and then start it again it gives me errors.
listenerRunnable = new Runnable() {
public void run() {
//This thread will listen keep listening to the UDP traffic and put it to the log source string
try {
sock = new DatagramSocket(portNumber);
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while(keepListening) {
try {
pack = new DatagramPacket(recievedData, BUFFERSIZE);
sock.receive(pack);
String data = new String(pack.getData(), 0, pack.getLength());
addToLog(data);
System.out.println(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sock.close();
}
}
};
/**
* Function to start the listening thread.
*/
public void startListening(int portNum) {
keepListening = true;
portNumber = portNum;
listenerThread = new Thread(listenerRunnable);
logSource_buffer = "";
logSourcehtml_buffer = "";
logSourcehtml_temp = "";
ipListIndex_beg = 0;
ipListIndex_end = -1;
if(!listenerThread.isAlive()) {
listenerThread.start();
}
}
/**
* stops the listening thead. When the listening thread sees that keepListening is set to false
* it will reach the end of its loop, close the socket, and the thread will die.
*/
public void stopListening() {
keepListening = false;
}
It gives me the following error:
logUpdatingThread has entered synchronized block!!!
java.net.SocketException: Unrecognized Windows Sockets error: 0: Cannot bind
at java.net.PlainDatagramSocketImpl.bind0(Native Method)
at java.net.PlainDatagramSocketImpl.bind(Unknown Source)
which points to the line with sock.recieve(pack);
It seems like for some reason the socket isn't closing because, I think, its waiting at sock.recieve(pack) and never gets out of the while loop to close the socket. How would I get around this though?
Thanks
As Peter Tillemans said, you should set a receive timeout so that you're not sitting there trying to receive() for ever.
Also, keep hold of the Thread object returned by new Thread(listenerRunnable) so that your stopListening() method can wait for the thread to die:
public void stopListening() {
keepListening = false;
listenerThread.join();
}
You'll have to add a setSoTimeout(timeout) before calling receive. This will regularly throw SocketTimeoutExceptions, but keeping the Datagram socket open. This will allow you to regularly check the loop variable.
Additionally you should move the loop inside the first try-catch block and add a finally block to close the socket.
like :
try {
sock = new DatagramSocket(portNumber);
sock.setSoTimeout(250);
while(keepListening) {
try {
pack = new DatagramPacket(recievedData, BUFFERSIZE);
sock.receive(pack);
String data = new String(pack.getData(), 0, pack.getLength());
addToLog(data);
System.out.println(data);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} catch (SocketException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} finally {
sock.close();
}