I'm trying to create a simple Chat program, I found all kinds of example but yet I do try to accomplish it from scratch.
I have Server class (extends thread) and a GUI class, when either Connect or Disconnect buttons are clicked the GUI is halted (stuck)
Server code:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
*
* #author Shahar Galukman
*/
public class ChatServer extends Thread{
ServerSocket ss;
boolean serverStopped = false;
private int port = 18524;
public ChatServer(){
serverStart();
}
private void serverStart(){
//Create new server socket
try {
ss = new ServerSocket(port);
} catch (Exception e) {
System.out.println("An error eccurd connection server: " + e.getMessage());
}
//wait for clients to connect
while(!serverStopped){
try {
Socket clientSocket = ss.accept();
/*
* Code will halt here until a client socket will be accepted.
* Below a new client thread will be created
* enabling multi client handling by the server
*/
//create new ChatClientThread here
} catch (IOException ex) {
System.out.println("Error accpeting client socket");
}
}
}
//Stop the server
public void stopServer(){
serverStopped = true;
ss = null;
}
}
And i have a simple SWING GUI having connect and disconnect buttons, I'm using a inside class called Handler to add action listener to the bottons.
Handler class (located in the end of the GUI class:
//inner class
class Handler implements ActionListener
{
//This is triggered whenever the user clicks the login button
#Override
public void actionPerformed(ActionEvent ae)
{
ChatServer server = new ChatServer();
//checks if the button clicked
if(ae.getSource()== connectButton)
{
try{
server.start();
serverStatusField.setText("Connected");
}catch(Exception e){
e.printStackTrace();
}
}else if(ae.getSource()== disconnectButton){
server.stopServer();
serverStatusField.setText("Disconnected");
}
}
}
Also in the GUI class I'm adding the action listener to the bottuns as follows:
public GUI() {
initComponents();
//create new handler instance
handle = new Handler();
connectButton.addActionListener(handle);
disconnectButton.addActionListener(handle);
}
When I click on the connect bottun a new Server thread is starting, as far as I understand. so why is the GUI get stuck? Should I use multi threading here?
In your serverStart method, you have a sort of infinite loop which waits for the server to stop. When this button is called, the caller thread while certainly loop forever and block other calls.
In Swing, GUI is handled by the main thread. So if you call serverStart from the main thread, the gui will block until the loop is broken which will never happen.
Therefore, yes you should use mutithreading and call serverStart on another independant thread.
Normally, you should go for the following solution:
Thread for GUI calls (dynamic gui handling ...)
Thread(s) for heavy backend work (Socket connections, Data loading ..)
EDIT:
Here's a nice oracle tutorial about thread:
http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html
2nd EDIT:
There is also something wrong in your code. Why is the method serverStart called in the constructor of ChatServer and not on the run method overriden from Thread? In that case, the infinite loop is called on the main thread when the ChatServer thread is constructed. I think you should call the serverStartin the run method of Thread:
ex:
public class ChatServer extends Thread{
....
public ChatServer(){
}
#Override
public void run {
serverStart();
}
Related
In following code i am trying to start and stop the server on button using java applet.Start works good using thread but i want to stop the server on button. I have used volatile variable.Still i am not getting the server stop..
here is code:
public class TCPServer extends Thread {
public static final int SERVERPORT = 8002;
private boolean running = false;
public volatile boolean stop = false;
public Socket client = null;
public static void main(String[] args) {
ServerBoard frame = new ServerBoard();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public void run() {
super.run();
running = true;
try {
System.out.println("Server Has Started........ \n Waiting for client........");
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
try {
while (!stop && running) {
client = serverSocket.accept();
System.out.println("Connection Accepted......");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String usercmnd = in.readLine();
if (usercmnd != null) {
Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec(usercmnd);
}
}
if (stop) {
serverSocket.close();
client.close();
System.out.println("Server Has Stopped");
System.exit(0);
}
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
}
public void requestStop() {
stop = true;
}
}
But whenever i click the stop button which will stop the server.Its not showing any output on console as i expected by the code.Its also not showing any error
here is code of stop button
stopServer = new JButton("Stop");
stopServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
stopServer.setEnabled(false);
startServer.setEnabled(true);
mServer = new TCPServer();
mServer.requestStop();
}
});
It doesn't stop because you create a new instance before stopping it and you don't even start it first while you are supposed to call requestStop() on your current instance of TCPServer.
// Here you create a new instance instead of using the existing one
mServer = new TCPServer();
mServer.requestStop();
in your ActionListener implementation for the stop button, you are accessing a different instance of TCPServer (as you are creating a new one). So you set the value "Stop" to a second object. It has no impact on the first instance that was created with the start button.
Try to instanciate the TCServer outside of your implementation of the action listener for both buttons and use that single instance for both.
Due to https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#accept()
ServerSocket::accept is a blocking method, so stop variable can only be checked between successful connections.
You can either set a ServerSocket timeout using ServerSocket::setSoTimeout (and catch SocketTimeoutException), or interrupt Server thread and catch InterruptedException.
Both exceptions will be throwed from ServerSocket::accept.
Note, that thread interruption is highly preferred over timeouts and repeatly exception catching.
Try this:
public void requestStop() {
stop = true;
interrupt();
}
However, in this case, we can not guarantee, that already processing logic will successfully shutdown.
Also, you try invoke requestStop for new instance of TCPServer, instead already existing.
your code client = serverSocket.accept(); is blocking. So once you clicked "stopServer" button, you requested the stop, but it will be acted upon only once a client sends a next request to the server. What you need to do is to run your logic in your method run() in a separate thread and catch there InterruptedException and ClosedByInterruptException and clean up and return there. On your stopButton click you will invoke interrupt() method on your Thread. Read about it in here
I am doing a project about chatting application. I'm using sockets. I'm creating this JFrame that gives me the option to connect as a server or a client. When I run my Options JFrame (choose to run as server or client) and I press server button some of my code gets skipped in the action listener. I already spend hours debugging and I don't know why some of my code gets skipped.
private void serverBtnMtd() {
try {
System.out.println("Running server Method");//Testing
MyServer myServer = new MyServer();//server gets Created and shows up
myServer.initializeServer();//Skipped
myServer.setVisible(true);//Skipped
System.out.println("End Running server Method");//Testing
} catch (Exception e) {
e.printStackTrace();
}
}
Action listener
btnServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
serverBtnMtd();
}
});
My Main Method
public class MyMain {
public static void main(String args[]) {
ServerOrClient mainApp = new ServerOrClient();
mainApp.setVisible(true);
mainApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
When I run my server class without the options JFrame everything runs. All of the skipping of code happens on the Action listener. I did some println's to test if all my code gets run and only the "Running server Method" shows up in my command line.
Server generally have infinite loops. So your code isn't skipped, just the new MyServer thing doesn't finish to resume your code. Put the code in a new thread.
You need to add:
setFocusable(true);
to your constructor
I'm writing a Java GUI multiplayer game.
I have a GUI where user can enter port number and click on "start server" which will initiate game server and bring up another GUI frame. But my program freezes when the button is clicked.
Is it okay to start server using this way or how can I code so that server will be started and waiting for players to be connected and at the same time display another GUI frame (written in a separate class)? Thanks in advance.
// part of GUI code
start = new JButton ("Start Game Server");
start.addActionListener (new ActionListener() {
public void actionPerformed (ActionEvent event) {
DEFAULT_PORT = Integer.parseInt(port.getText());
fgServer.run();
fgServerFrame = new FishingGameServerFrame();
//frame.dispose();
}
});
--
// server code
public class FishingGameServer {
private static int DEFAULT_PORT = 0;
public void run()
{
int port = DEFAULT_PORT;
port = Integer.parseInt(FishingGameConnectServerFrame.portNumber());
System.out.println("port #: " + port);
//setup server socket
ServerSocket reception_socket = null;
try {
reception_socket = new ServerSocket (port);
System.out.println("Started server on port " + port);
}
catch (IOException e) {
//to get text in GUI frame
System.out.println("Cannot create server");
System.exit(0);
}
for (;;) {
Socket client_socket = null;
try {
client_socket = reception_socket.accept();
System.out.println("Accepting requests from:" + client_socket.getInetAddress());
}
catch (IOException i) {
System.out.println ("Problem accepting client socket");
}
new FishingGameThreadedServer(client_socket);
}
}
public static void main (String[] args) {
new FishingGameServer().run();
}
You call fgServer.run();, which eventually calls client_socket = reception_socket.accept(); within an infinite loop.
This is preventing the Event Dispatching Thread from been able to run, by blocking (once within the neverending for-loop and once when using accept) it can not process the Event Queue, which is responsible for, amongst other things, processing paint requests.
Swing is a single threaded environment, it is also not thread safe. This means:
You should never perform any long running or blocking operations within the context of the EDT and
All updates and interactions with the UI must be made from within the context of the EDT
Take a look at Concurrency in Swing for more details
You could use a Thread instead or a SwingWorker which provides functionality to more easily publish updates back to the EDT...
My Server is build around support to update the listening socket, by doing so I use the following method. my problem occurs after this method is called for the second time, this is first called at start up from the main method then later it is called by clicking a button in a JFrame. what happens is that the JFrame freezes when this method is called via button, as you can see by the code I tried to make this method run a server in a new thread but it hasn't changed my outcome. Does anyone know how to fix this? or at least what is causing it? also any code after the method is called in the main doesn't get execute, so I believe it is a thread problem. (MiniServer extends Thread and is used to handle each connected client individually)
public static void startListening(final int port)
{
listeningThread = new Thread()
{
public void run()
{
try {
serverSocket = new ServerSocket(port);
while(!stop)
{
boolean loop = true;
while (loop)
{
serverSocket.setSoTimeout(1000);
try{
clientSocket = serverSocket.accept();
loop = false;
} catch (SocketTimeoutException e){
}
}
if(!clientSocket.equals(null))
{
MiniServer mini = new MiniServer(clientSocket);
mini.start();
clientSocket = null;
}
}
} catch (IOException e) {
}
}
};
listeningThread.run();
}
You need to be calling listeningThread.start(), which will create a new thread. Right now, you're just calling the thread's run() method on the current thread. The first time you do that it works, since you're on the main thread. The second time, though, you're on the UI thread, reacting to the button press. This causes your UI thread to block.
I'm trying to create a chat program in java but I had a problem when I run the server form, that the components I used to draw won't appear.
this is the code I used in the run of the form :
public void run() {
Server s = new Server();
s.setVisible(true);
// Etablir la connexion
try
{
ServerSocket ecoute;
ecoute = new ServerSocket(1111);
Socket service = null;
System.out.println("Serveur en attente d'un client !");
while(true)
{
service = ecoute.accept();
System.out.println("Client connécté !");
DataInputStream is = new DataInputStream(service.getInputStream());
s.jTextArea1.setText("Client dit : " + is.readUTF().toUpperCase());
service.close();
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
You said nothing happens when this code is ran. The presence of a public void run() method tells me that this is a thread, or at least a Runnable.
Because of the while(true), if this thread is not started in the proper manner, it will not run independently; that is it will hold up the entire program.
Instead of calling thread.run();, call thread.start();. This will call the run method for you, after starting a new thread that will run in parallel to the main thread.
If this code is not in a thread, and you just used public void run() by chance, then it will still provide the same problem for you.
For more information, refer to the Documentation on Threads