public void doConnect(){
try{
statusArea.append("Starting server.....\n");
serverSocket = new ServerSocket(5555);
statusArea.append("Server started.\n");
statusArea.append("Waiting for client connection....\n");
socket = serverSocket.accept();
statusArea.append("Client connected.\n");
inStream = new ObjectInputStream(socket.getInputStream());
} catch (IOException e){
e.printStackTrace();
}
}
All strings be appended to text area only after I start server and client connected. So I want to it be shown as my code, step by step. How solve?
You're blocking the Event Dispatching Thread, preventing it from updating the screen.
Take a look at Concurrency in Swing for more details.
I suggest you use a SwingWorker to execute the socket code in a background thread and use the SwingWorker's functionality to safely update the UI. See Worker Threads and SwingWorker for more details
Something like this for example
Related
I am writing a Server-Multiclient communication application, and I need to make a Thread that loops and accepts clients. My current code is:
Thread acceptor = new Thread() {
public void run() {
while(true){
System.out.println("looking for clients");
try{
Socket s = serverSocket.accept();
clientList.add(new ConnectionToClient(s));
}
catch(IOException e){ e.printStackTrace(); }
}
}
}
};
acceptor.setDaemon(true);
acceptor.start();
However, when I run my application, the text looking for clients only appears one time, and no clients can connect.
I don't understand why my while(true) loop isn't actually looping, and only running once.
EDIT:
The ConnectionToClient constructor is:
ConnectionToClient(Socket socket) throws IOException {
this.socket = socket;
in = new ObjectInputStream(socket.getInputStream());
out = new ObjectOutputStream(socket.getOutputStream());
Thread read = new Thread(){
public void run(){
while(true){
try {
Object obj = in.readObject();
messages.put(obj);
} catch(IOException | ClassNotFoundException | InterruptedException e) {
e.printStackTrace();
}
}
}
};
read.start();
}
You're calling acceptor.setDaemon(true);.
Its Javadoc explains:
Marks this thread as either a daemon thread
or a user thread. The Java Virtual Machine exits when the only
threads running are all daemon threads.
So you're marking your only running thread as a daemon thread (since your main thread ends when the main method ends). You're lucky that you got one iteration of the loop, since your VM almost immediately exits as there are no more non-daemon threads.
Solution: remove the line that reads acceptor.setDaemon(true);
Your updated post shows the other problem, the constructor ConnectionToClient(Socket socket) inadvertently tries to read from the Socket, which blocks the acceptor thread until the client sends data.
The problem is the constructor of ObjectInputStream tries to read the header of the object stream.
Therefor, you should move the construction of the ObjectInputStream and ObjectOutputStream into the read Thread, so that this doesn't block the acceptor Thread.
Ok, thanks to #ErwinBolwidt.
The problems were:
1) The .setDaemon(true) was causing problems.
2) Creating the ObjectInputStream before the client was connected was reading the header that needed to be sent to the server, and blocking the client from sending it to the server. Moving that to the read thread allowed the client to actually connect to the server.
Thanks again #ErwinBolwidt.
I am currently developing a chat application which is quite basic overall, however I am encountering problems when receiving strings from both the client and the server side. I am using a thread to passively listen on the socket for incoming messages, which is where I suspect the problem to be. Am I doing this the right way?
Source:
Code for sending strings:
send.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
messageBuffer = message.getText();
out.println(messageBuffer);
chat.append(username + ": " + messageBuffer + "\n");
message.setText("");
}
});
I then have this which passively listens (problem is probably here):
public void run(){
while(true){
try {
messageBufferIn = in.readLine();
System.out.println(in.readLine());
chat.append(recipient + ": " + messageBufferIn + "\n");
} catch (IOException e) {
e.printStackTrace();
}
}
}
Im also calling the thread using this:
public static void startChatting(){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Thanks for any help you can provide, Im still new to threads overall so my mistake might be quite mediocre.
Edit: The problem is when I try sending a message to the receiver, nothing comes through, I can confirm that they are connected. In fact the System.out.println(in.readLine()); doesnt come through at all, not even a "null" output.
you have got issue with Concurency in Swing, Swing GUI don't know that you running / open the Socket on Background Task,
all updates to the Swing GUI must be done on EDT, otherwise nothing happened or you got a few exceptions
have to wrap all updates from Background Task (in your case Runnable#Thread) to the invokeLater for Swing GUI
while(true){ is endless loop put there Boolean variable instead of true, then you can to stop, start or restart whatever in your case Socket
in the case that send.addActionListener(new ActionListener(){ runs only once time (if user invoked by JButtons click) then to use SwingWoker for opening Socket, SwingWorker quite good guarantee that all output should be done on EDT
difference betweens Runnable#Thread and SwingWorker is that SwingWorker is designated to run only once times
I suspect your main problem is that you're not flushing the OutputStream. You'll want to add out.flush() after you've finished writing to it and want to send the message. For example, your ActionListener would look like this:
send.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
messageBuffer = message.getText();
out.println(messageBuffer);
out.flush();
chat.append(username + ": " + messageBuffer + "\n");
message.setText("");
}
});
If you don't do this, your OutputStream will sit there until it's buffer's full (which will be a lot of messages).
I've recently gotten into trying to make server-client connections. I was able to make a 1 on 1 connection with no problems, but now i'm trying to make a server that accepts multiple clients and i'm running into a problem where i can't make the server listen to connections while there is one established... I'm not sure if i made myself clear but here's my code:
-The main loop that waits for connections:
public class ChatMultiServer {
public static void main(String []args){
int socknum = 124;
ServerSocket serverSocket;
Socket clientSocket;
while(true){
////opens socket
try{
System.out.println("Opening port...");
new ServerSocket(124).close();
serverSocket = new ServerSocket(socknum);
}catch(Exception e){System.out.println("Error 101 = failed to bind to port "+socknum+"."); break;}
//////accepts connection
try{
System.out.println("Waiting for connections...");
clientSocket = serverSocket.accept();
}catch(Exception e){System.out.println("Error 102 = failed to accept port "+socknum+"."); break;}
/////
try{
System.out.println("Initializing thread...");
new Thread(new CMSThread(clientSocket));
}catch(Exception e){System.out.println("Error 103 = failed to create thread."); break;}
try{
serverSocket.close();
}catch(Exception e){System.out.println("Error 105 = failed to close socket.");}
}
}
}
-The thread that handles the connections:
public class CMSThread extends Thread{
Socket socket;
BufferedReader in;
PrintWriter out;
String username;
char EOF = (char)0x00;
public CMSThread(Socket s){
socket = s;
run();
}
public void run(){
try{
System.out.println("Setting up streams...");
in = (new BufferedReader(new InputStreamReader(socket.getInputStream())));
out = new PrintWriter(socket.getOutputStream());
}catch(Exception e){System.out.println("Error 204 = failed to get streams");}
try{
out.print("Welcome! you can quit at any tyme by writing EXIT.\nLet me introduce myself, I'm 'testprogram 1', but that doesn't really matter since you'll do the talking.\nWhat's your name?"+EOF);
out.flush();
username = in.readLine();
out.print("<b>"+username+"</b>, that's a nice name.\nWell, i'll shut up now. Have fun talking to yourself while whoever is running the server observes your conversation.\n"+EOF);
out.flush();
}catch(Exception e){System.out.println("Are you effin kidding me!? -.- whatever... Error 666 = failed to chat.");}
}
}
My problem, once again, is that when the server gets a connection with a client(I'm using actionscript for the clients just because it's easier to make a GUI), it just waits until the thread is done running to start the loop again. I'm trying to make it loop at the same time as the thread handles the chat.
I was thinking maybe i needed to make a thread for the loop as well as the thread for handling the connection, but i'm not sure as to how i would go about doing that... Please let me know if my hypothesis was somewhat right, and if it was, some guidance towards the answer would be nice.
PS: I'm sorry if my code is a bit messy or if this is a stupid question, i haven't made a java program in a while...
You aren't actually starting your new Threads - you are just directly calling run(). As far as I can see, this means that you will be executing run() in the main thread that creates each CMSThread object.
To start a Thread, you have to call thread.start().
Also, I'm not sure why you are wrapping your CMSThread in another Thread - CMSThread extends Thread so it can be started in its own right. The wrapper Thread isn't being started either.
So you need:
new CMSThread(clientSocket).start();
and remove the run() call from the constructor of CMSThread
I am trying to build a simple desktop application where the user enters the url in a text field and clicks on the submit button to send the GET request for that page.I am trying to open a socket to connect to the host in the submit button mouse clicek event handeler but the GUI gets stuck. I have to close it from task manager.
private void SubmitButtonMouseClicked(java.awt.event.MouseEvent evt)
{
Socket s = null;
String website = URLTextBox.getText();
String host = "111.65.23.56"; //this could be any host
int port = 80;
try
{
System.out.println("I am opening socket");
s = new Socket(host,port); **// the code stuck here :(**
System.out.println("socket opened");
}
catch(IOException e){ }
// and the code follows......
}
please help me out.....
You'll almost certainly want to create a separate thread for the Socket code, and most likely using the excellent Socket Selector family of classes:
Using a Selector to Manage Non-Blocking Sockets
I'm trying to create a client server game using java sockets. I have a thread server which controls the logic of the game. I also have client threads that communicate with the server. I use multiple client handler threads to facilitate server-to-client communication. I use multiple threads to communicate with other client threads using sockets.
Now, I have a problem on how to facilitate communication between the server thread and the multiple client threads. For example, should the server select the next player to play, how should it signal the client handler thread, and in turn communicate with the client thread through sockets?
I have done this before in the following way. I have a Server socket
public Server(int port, int numPlayers) {
game = new PRGameController(numPlayers);
try {
MessageOutput.info("Opening port on " + port);
ServerSocket clientConnectorSocket = new ServerSocket(port);
MessageOutput.info("Listening for connections");
while (!game.isFull()) {
// block until we get a connection from a client
final Socket client = clientConnectorSocket.accept();
MessageOutput.info("Client connected from " + client.getInetAddress());
Runnable runnable = new Runnable() {
public synchronized void run() {
PRGamePlayer player = new PRGamePlayer(client, game);
}
};
new Thread(runnable).start();
}
} catch (IOException io) {
MessageOutput.error("Server Connection Manager Failed...Shutting Down...", io);
// if the connection manager fails we want to closedown the server
System.exit(0);
}
}
Then on the client side, I have something like this..
public void connect(String ip) {
try {
comms = new Socket(ip, 12345);
comms.setTcpNoDelay(true);
// get the streams from the socket and wrap them round a ZIP Stream
// then wrap them around a reader and writer, as we are writing strings
this.input = new CompressedInputStream(comms.getInputStream());
this.output = new CompressedOutputStream(comms.getOutputStream());
this.connected = true;
startServerResponseThread();
} catch (IOException e) {
ui.displayMessage("Unable to connect to server, please check and try again");
this.connected = false;
}
if (connected) {
String name = ui.getUserInput("Please choose a player name");
sendXML(XMLUtil.getXML(new NameSetAction(name, Server.VERSION)));
}
}
/**
* This method sets up the server response thread. The thread, sits patiently
* waiting for input from the server, in a seperate thread, so not to hold
* up any client side activities. When data is recieved from the server
* it is processed, to perform the appropriate action.
*/
public void startServerResponseThread() {
// create the runnable that will be used by the serverListenerThread,
// to listen for requests from the server
Runnable runnable = new Runnable() {
public void run () {
try {
// loop forever, or until the server closes the connection
while (true) {
processRequest(input.readCompressedString());
}
} catch (SocketException sx) {
MessageOutput.error("Socket closed, user has shutdown the connection, or network has failed");
} catch (IOException ex) {
MessageOutput.error(ex.getMessage(), ex);
} catch (Exception ex) {
MessageOutput.error(ex.getMessage(), ex);
} finally {
(PRClone.this).connected = false;
// only shutdown the server if the listener thread has not already been
// destroyed, otherwise the server will have already been shutdown
if (serverListenerThread != null) {
// shutdown the thread and inform the application the communications has closed
MessageOutput.debug("Shutting down server listener Thread");
}
}
}
};
// create the thread
serverListenerThread = new Thread(runnable);
// start the thread
serverListenerThread.start();
}
The client is able to send requests to the server via the outputstream, and read server data from the input stream.
The server can accept requests from the client, and process it in the GameController, and can also send notifications from the server using outputstream, again in the GameController.
EDIT: Also, I should note that all my communication is done via XML, and the controller on the client or the server decodes the XML and performs the relevant request.
Hope this helps. It certainly does the job for me, and allows my multi-player games to work well.
I suspect that your client threads are hanging on a blocking read operation. To "release" these threads and make them send data instead, you'd have to interrupt them through thread.interrupt(). (Which would cause the blocking read to throw an InterruptedException.)
However, I've written a few network games myself, and I would really recommend you to look into the java.nio packages and especially the Selector class. Using this class you could easily make the whole server single-threaded. This would save you a lot of headaches when it comes to synchronizing all those client threads.
I think using an existing communication infrastructure like ActiveMQ would be very useful here to deal with the low-level piping stuff and allow you to tackle the game design issues at a higher conceptual level rather than dealing with the low-level intricacies.
That being said. If I understood you then you have a game-client with mutiple threads, one of which deals with comms to the server. On the server there is a comms thread for each client and the game server logic.
I would only use sockets for remote communication and Queues for communication between the server threads. On the queues send immutable objects (or copies) back and forth so you do not need to synchronize access to the data in the messages. As a base for synchronisation you can block on the Socket or a BlockingQueue, then you do not need to manually synch things, however this requires careful protocol design.