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
Related
When my SECOND client connect to my server I got this error:
Exception in thread "main" java.net.SocketException: Connection reset
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:186)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:140)
at java.base/java.net.SocketInputStream.read(SocketInputStream.java:200)
at java.base/java.io.DataInputStream.readLine(DataInputStream.java:518)
at Main.main(Main.java:24)
I don't know what am I doing wrong.
FIRST client works normal
My code:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class Main {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(50505);;
Socket socket;
while (true) {
socket = serverSocket.accept();
while(socket.isConnected()) {
String v;
DataInputStream in;
InputStream in_sock;
in_sock = socket.getInputStream();
in = new DataInputStream(in_sock);
v = in.readLine();
System.out.println(v);
OutputStream output = socket.getOutputStream();
DataOutputStream out = new DataOutputStream(output);
out.writeChars("123\n");
out.writeChars("123\n");
out.writeChars("123\n");
}
}
}
}
PS: How can I share error on stackoverflow? like code?
So the big issue, like some other people have said, is that your server can only accept one connection because of the lack of multi-threading.
Right now your server waits for a connection to the port specified
socket = serverSocket.accept();
Then while your socket is still connected you read a line from the socket, print it out to System.out, and then write back to the socket all in a loop. Now this comes into issue because next time a client tries to connect to your serverSocket, it can no longer accept connections because your code is stuck in a loop of reading and writing data from one Socket.
The way to fix this is to introduce multithreading in the way that Milen mentioned above.
Your code should look something like this.
public class Main {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(50505);
while (true) {
Socket socket = serverSocket.accept();
SocketHandler h = new SocketHandler(socket);
h.start();
}
}
}
public class SocketHandler extends Thread{
Socket clientSock;
public SocketHandler(Socket sock){
clientSock = sock;
}
public void run(){
while(clientSock.isConnected()) {
String v;
DataInputStream in;
InputStream in_sock;
in_sock = socket.getInputStream();
in = new DataInputStream(in_sock);
v = in.readLine();
System.out.println(v);
OutputStream output = socket.getOutputStream();
DataOutputStream out = new DataOutputStream(output);
out.writeChars("123\n");
out.writeChars("123\n");
out.writeChars("123\n");
}
}
}
Now this code has a loop that accepts connections, and spawns a new thread for every connection!
I would recommend looking at a few things. First, if you check the Java Docs for ServerSocket you will see this constructor
ServerSocket(int port, int backlog)
Creates a server socket and binds it to the specified local port number, with the specified backlog.
The backlog is the number of incoming connections the server socket can hold onto and store in some sort of buffer until they can be accepted. This is useful if a client is connecting when your accepting loop is in the middle of creating the socket handler. I would recommend putting it at the max number of clients you're expecting.
Secondly, look up the Thread class in the Javadocs. To extend Thread successfully you need to overwrite run(). This method is the method that the thread will execute with. To spawn the thread, you call ThreadObject.start(). You can think of start() as just calling run().
From the "Writing the Server Side of a Socket" tutorial from Oracle:
... the server can service them simultaneously through the use of threads—one thread per each client connection.
The basic flow of logic in such a server is this:
while (true) {
accept a connection;
create a thread to deal with the client;
}
The thread reads from and writes to the client connection as necessary.
In that tutorial you'll also find links to a server (KKMultiServer) and thread (KKMultiServerThread) sample implementations.
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.
So I created a basic client-server program in java. It starts out like this:
Client connects to Server
Server asks for Client's name
Client responds with name
Server greets Client
After this, Client speaks and the Server repeats the words back
I got this to work without too much trouble using this tutorial. The problem comes whenever I try to introduce multiple clients. I thought that it would work because I'm using multiple threads, however, the second clients just hangs until the first client quits and then it starts it work (the server does accept input from the second client, but it doesn't respond with anything until the first client quits).
Here is the code I'm using:
import java.net.*;
import java.io.*;
public class Server extends Thread {
private ServerSocket listener;
public Server(int port) throws IOException {
listener = new ServerSocket(port);
}
public void run() {
while(true) {
try {
Socket server = listener.accept();
DataOutputStream out = new DataOutputStream(server.getOutputStream());
out.writeUTF("What is your name?");
DataInputStream in = new DataInputStream(server.getInputStream());
String user_name = in.readUTF();
out.writeUTF("Hello "+user_name);
while(true) {
String client_message = in.readUTF();
out.writeUTF(client_message);
}
}
catch(IOException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
int port = 6006;
try {
Thread t = new Server(port);
t.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}
Can someone explain what I'm doing wrong?
I have looked at the using Runnable instead of Extends Thread, but I ran into even more problems there, so I want to try and work with this first.
Incoming connections are only handled by the line listener.accept();. But after you got a client connected, you're stuck in the while loop. You need to create a new Thread (or Runnable executed on an ExecutorService if you expect high load), and start it, then immediately accept the next connection.
In a nutshell, this is what is going wrong.
You are using exactly ONE thread as the server.
Blocking this thread when you call listener.accept()
This is what you need to do:
Create two classes
1: Server - Similar to what you have now, but instead of doing the actual work of acting as an echo server, it just spawns a new Thread which starts listening on a NEW PORT (which you can select randomly), and sends the client the address for this new port. The client will then get the new port number and would try to connect to the server on the new port.
2: The Echo thread - This starts a new listener on the port passed, and does the job of echoing to whoever is listening.
OR:
You start a UDP server rather than a TCP server, and all this will not matter then, but that is out of the purview of this specific question.
I am trying to write a program that acts as a proxy server.
Proxy server basically listens to a given port (7575) and sends the request to the server.
As of now, I did not implement caching the response.
The code looks like
ServerSocket socket = new ServerSocket(7575);
Socket clientSocket = socket.accept();
clientRequestHandler(clientSocket);
I changed the above code as below: //calling the same clientRequestHandler method from inside another method.
Socket clientSocket = socket.accept();
Thread serverThread = new Thread(new ConnectionHandler(client));
serverThread.start();
class ConnectionHandler implements Runnable {
Socket clientSocket = null;
ConnectionHandler(Socket client){
this.clientSocket = client;
}
#Override
public void run () {
try {
PrxyServer.clientRequestHandler(clientSocket);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
Using the code, I am able to open a webpage like google. However, if I open another web page even I completely receive the first response, I get connection reset by peer expection.
1. How can I handle this issue
Can I use threading to handle different requests. Can someone give a reference where I look for example code that implements threading.
please excuse my writing errors...
I'm using NetBeans to run a homemade server and a client, and it all works fine. As I said before, I'm using "Socket" on my client, and "ServerSocket" on my sv. I'm also using JDBC Mysql in the server.
The problem starts when I generate both java files in their distributable folders and use them. The client sends information to the server (it starts with .getOutputStream() and .getInputStream(), then .flush() ), but the server doesn't receive any message. I tried seeing where it stops and it's in
clients[i] = new Client (server.accept(), i);
The crazy thing happens when I try executing my server from NetBeans and the client from my desktop... It works! So the server must be the problem. I'm also using an opened UDP port, and i'm looking for the IP of the server on 192.168.0.10 (which is my computer, in LAN).
I hope someone can help me, thanks in advance!
Here I paste my code, i'm sorry some variables are in spanish:
public ServidorMultiCliente() {
super("Servidor MultiCliente");
initComponents();
try{
servidor = new ServerSocket( 500, maxNumberClients);
}catch(IOException excepcion){
excepcion.printStackTrace();
System.exit(1);
}
serverWriteBox.append("Server iniciated, waiting for connections..."); }
I run these, from the Server:
public void ejecutar(){
clientsAcceptor.start();
messagesListener.start(); }
Where clientsAcceptor is:
private class aceptadorClientes extends Thread{
public void run(){
for( int i = 1; i < maxNumberClients; i++ ){
try{
clientes[i] = new Cliente (servidor.accept(), i); // **Here it stops**
// It never reaches here... (without using NetBeans)
clientes[i].start();
clientes[i].aceptado = true;
}catch(IOException excepcion){
excepcion.printStackTrace();
}
}
That's how I accept clients in different threads. I make the same thing with messageListener, which is a new thread for every new client. It's in a loop, always listening. And here I paste my executable Client, which is different from the Cliente class I was using in ServidorMultiCliente:
public Cliente(){
}
public Cliente(String host){
this.host = host;
this.executeConnection();
}
public void executeConnection(){
int connect = 0;
try {
cliente = new Socket(InetAddress.getByName(host), 500);
conectar = 1;
} catch (IOException ex) {
conectar = 0;
this.ejecutarConexion();
}
if(conectar == 1){
obtainFlows();
}
}
private void obtainFlows(){
try{
output= new ObjectOutputStream( cliente.getOutputStream());
output.flush(); // Here I should be "connected"
input = new ObjectInputStream(cliente.getInputStream());
} catch(IOException ex){
this.initiateDisconnection();
}
sendFlows("I'm connected!");
new messageListener().start(); // This is a thread
}
ServerSocket#accept is a blocking call. It listens to a port and returns a Socket when a client connects. You don't show very much of your server logic but it seems you put clients in an array so you obviously want to support more than one client. You don't show if your Client class starts a thread and returns immediatly.
You should have a server loop that just listens to a server socket and creates clients after it retrieved a client socket. Even if you do this in your Client constructor (I can't tell without the code) it is not a very good place for this and seriously hinders debugging.
If you don't start threads for your clients this would explain a server that "stops" (if "stops" means "blocks" and not "crashes"). See "Writing the Server Side of a Socket" in the Java Tutorial for a detailed explanation.
I can't think of why it behaves different when started via Netbeans. A little bit more of code context is needed.