Java Sockets: One Server and Multiple Clients - java

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.

Related

Threading in client-server socket program - proxy sever

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.

How to make communication between one server and multiple client in Java Socket Programming?

I have two java applications, one is web app and another is simple java app, So I am using Socket programming for communication between them.
I made one SocketServer which is a Thread, in which I created ServerSocket serverSocket = new ServerSocket(6789)
And in my web app I created Socket client = new Socket("localhost", 6789);
My server sends some data to client and client will start some other work, but if I want to run another client i.e. server will send different parameters and client have to start processing what should I do?
Because server is already started on '6789' port and first client also with the same port. How can I start client with another port?
Every time Server must have to started first and then client.
I think client will not found server till both are having same ports.
Am I have to create another server instance with different port and then invoke client??? But How can my client will know on which port server is started?
For Example:
Imagine I have UI like:
start MIlind
start xyz
start abc
and click on strart it will call client and start process, If an start Milind first then How will I start xyz?
because 'start Milind' started client and server at port 6789, How will other start process works?
It seems like a lot of overhead to create a server/client app just for a web app to communicate with a local java program (and even more so to duplicate this process to do more than one thing at a time). If you are looking for concurrent processing in the background of a web app, you can always just create a thread (or multiple threads) to do the work. Or is there a reason why the simple java app can't be embedded in the web app?
You need to split off threads when accepting your socket connections server side. This is very easily done with serversocket. A very rudimentary (untested!) implementation:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
class Server {
private ServerSocket socket;
public Server() {
try {
this.socket = new ServerSocket(6789);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void go() throws IOException {
while(true) {
Socket sock = socket.accept();
new Thread(new ClientSession(sock)).start();
}
}
public static void main(String[] args) {
Server server = new Server();
try {
server.go();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
class ClientSession implements Runnable {
private final Socket clientsocket;
ClientSession(Socket sock) {
this.clientsocket = sock;
}
#Override
public void run() {
//do stuff, like read from socket.
}
}
}
Note that you don't need to change the port at all.

Java; trying to make a server that accepts multiple client connections

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

My server stops working when reading .accept(), using Sockets

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.

How to facilitate communication between the server thread and the multiple client threads in Java

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.

Categories