Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Your 'n' thread has no loop, meaning its gonna run once (accept a connection), then die off.</p> <pre><code>Thread n = new Thread(new Runnable() { public void run() { while(true) { //control this with your own boolean, or it will run forever try { addClient(); }catch(IOException e) { } } } }); </code></pre> <p>Dont worry, your thread will be paused at 'ss.accept()', since it will wait until a socket is accepted to continue.</p> <pre><code>Thread thread = new Thread(new Runnable() { public void run() { while(running) { String input; while((input = inputstream.readUTF()) != null) { //handle input } } } }); </code></pre> <p>Sorry, wrote that really quick, dont have much time. Ill come back and relate it to your code in a bit if it doesnt help.</p> <p>You need some way of continuously retrieving input from the Server's input stream, in which you can then handle the input.</p> <p>That loop loops each time you retrieve something from inputstream.readUTF() (and isnt null, of course). Hopefully that example will help you</p> <hr> <p>After actually reading your code and testing it, i have noticed that your structure seems a bit off. First, your <code>Thread n</code> in your server is responsible for accepting connections (<code>addClient()</code>), but you also call it first thing in your <code>Thread input</code>? </p> <p><code>Thread n</code> is handling accepting connections, so with the loop, <code>Thread n</code> is fine. <code>Thread input</code> is handling input retrieved from clients. This is where you are getting confused.</p> <p>Each client should have their own InputStream and OutputStream server-sided. Similar to how you have a list for Sockets (since you are gonna be creating multiple Sockets server-sided), you need multiple Streams aswell. For this, I suggest making a User class, then if anything, have your ArrayList for User, not Socket.</p> <pre><code>public class User extends Thread { //create a Thread for each connection to handle data seperately DataInputStream in; DataInputStream out; Socket socket; public User(Socket socket) { //creates a stream for the socket that the user connected with this.socket = socket; initStream(); } public void initStream() { //inits streams after socket is initiated (through ss.accept()) try { out = new DataOutputStream(socket.getOutputStream()); in = new DataInputStream(socket.getInputStream()); }catch(IOException e) { e.printStackTrace(); } } public void closeStream() throws IOException { //throws exception since i have a chance to catch it in my run() method out.close(); in.close(); socket.close(); } public void sendMessage(String string) { try { out.writeUTF(string); }catch(IOException e) { e.printStackTrace(); } } public void run() { //when thread starts, accept/handle data String input; try { while((input = in.readUTF()) != null) { //handle input } closeStream(); }catch(IOException e) { e.printStackTrace(); } } } </code></pre> <p><code>in.readLine()</code> is depreciated, which means it's out-dated and shouldn't be used (to avoid bugs). Now that you have your User class set up, which handles the data, you can now create a new User each time a connection is received.</p> <pre><code>public class Server() { public static ArrayList&lt;User&gt; userlist; public static synchronized void stop() { //synchronized in-case another thread other than the main thread stops the server if(!running) return; running = false; } public static void main(String[] args) { /* uses the JVM thread (main thread for applications), so if you dont wanna ** dedicate your entire server to accepting connections only (since Users are in new thread) ** create a new thread for the code in this void method. */ try { ServerSocket ss = new ServerSocket(8000); userlist = new ArrayList&lt;User&gt;(); User user; //holds the user so we can put it in the list, then start while(running) { user = new User(ss.accept()); list.add(user); user.start(); } }catch(IOException e) { e.printStackTrace(); } } } </code></pre> <p>Hopefully, that'll give you a better idea for how your server should run.</p> <p>As for your client.. Well, there are a ton of things you should realize:</p> <p>First, big problem, you're re-initializing your DataOutputStream each loop, which is gonna cause the stream server-side to close. Gotta take it out of the loop, possibly put it before (or look at my server example for a better idea of handling stream initialization).</p> <p>Second, the names should be kept on the Server, rather than the Client. This way, its easy to iterate through the names, check if its taken, ect..</p> <p>Third, nothing with networking, but seeing how you never refer to <code>Thread n</code> or <code>Thread input</code>, other than to start it, you should remove the reference variable. (even though im pretty sure local vars are picked up by the Garbage Collector, still looks nicer). Example:</p> <pre><code>public void method() { new Thread(new Runnable() { public void run() { //code } }).start(); new Thread(new Runnable() { //run method }).start(); } </code></pre> <p>Hope this helps you understand how a multi-threaded server works! :)</p> <p>PS: This is a very basic server, and really shouldn't be used for large scale applications. Creating new threads (new User()) can cause a lot of overhead, so its best to handle connections using an ExecutorService, or some other type of threadpool service. Good luck!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload