I have a problem with a socket server that I’m developing.
Firstly, the socket server has then follow class:
-
Class
Main_Servidor(Execute the server) -
Class
EjecutarServidor(Basically waiting for new connections and then run them as a sub-process) -
Class
ManejoConexion(receives a socket object from home, and writes and reads in the socket) -
Class
Panel_mensajes(Shows info about the socket connections in ajpanel) -
The client is a little program written in adobe air
The problem is when two or more clients are connected, only the last connected client can read the socket. I’ve already used the eclipse’s debugger for check step by step, but I can’t found the error.
Here is my code:
Main_Servidor Class:
public class Main_Servidor {
public static void main(String[] args) {
Panel_mensajes PanelMensajes = new Panel_mensajes();
PanelMensajes.setVisible(true);
EjecutarServidor ejectuarservidor = new EjecutarServidor();
ejectuarservidor.ejecutar();
}
}
EjecutarServidor Class:
public class EjecutarServidor {
private static final int puerto = 1025;
private static final int conexionesMaximas = 3;
private ExecutorService iniciarThread;
private static ServerSocket listener;
private static Socket socket;
private static boolean EsperarConexiones = true;
public EjecutarServidor()
{
//Crea la pila de sub-procesos y se la asigna al objeto iniciarThread
iniciarThread = Executors.newFixedThreadPool(conexionesMaximas);
}
public void ejecutar()
{
Panel_mensajes.MostrarMensaje("ESPERANDO CONEXIONES...\n\n");
try{
listener = new ServerSocket(puerto); //Esta a la escucha de nuevas conexiones
//en el puerto especificado.
GregorianCalendar fecha = new GregorianCalendar(); //Genera la fecha incluyendo la hora
while(EsperarConexiones){ //Mientras EsperarConexiones sea TRUE esperará por
//nuevas conexiones.
socket = null;
socket = listener.accept(); //Acepta la nueva conexión y la asigna a un objeto socket
//Muesta en pantalla los datos de la nueva conexión
Panel_mensajes.MostrarMensaje("NUEVA CONEXION " +
socket.getInetAddress().toString().replace("/", "") + ":"
+ socket.getPort() + ", "
+ fecha.getTime() + "\n" + "\n"
);
//Se crea un nuevo objeto ManejoConexion al cual se le pasa como parametro
//el objeto socket llamado 'socket' que contiene la nueva conexión
ManejoConexion con_nva = new ManejoConexion(socket);
//Ejecuta el nuevo objeto ManejoConexion como un nuevo sub-proceso.
iniciarThread.execute(con_nva);
}
} catch (IOException ioe) {
Panel_mensajes.MostrarMensaje("IOException en socket!: * " + ioe);
}
}
//Deja de escuchar nuevas peticiones
public static void cerrarServidor()
{
try
{
EsperarConexiones = false;
listener.close();
socket.close();
}catch(SocketException SoE)
{
Panel_mensajes.MostrarMensaje("SocketException por cerrar servidor, todo OK");
//SoE.printStackTrace();
}catch(IOException ioe)
{
Panel_mensajes.MostrarMensaje("IOException por cerrar servidor, todo OK");
//ioe.printStackTrace();
}finally
{
System.exit(0);
}
}
}
ManejoConexion Class:
import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
public class ManejoConexion implements Runnable {
private Socket server;
private String line;
private DataInputStream in;
private static PrintWriter out;
private static Protocolo proto;
private static Boolean ACTIVO = true;
ManejoConexion(Socket server) throws IOException {
//Recibe un objecto Socket e inicializa la variable server
this.server = server;
}
//Hace que se ejecute un objeto de esta clase como un sub-proceso
public void run () {
try {
//Recibe las tramas de datos desde el servidor
in = new DataInputStream (server.getInputStream());
//Envia tramas de datos al servidor
out = new PrintWriter(server.getOutputStream());
this.responderPeticiones("+OK");
//Mantiene abierto el flujo de datos desde el servidor mientras no se cumplan las
//condiciones.
Panel_mensajes.MostrarMensaje(Thread.currentThread() + "\n");
while((line = in.readLine()) != null && !line.equals("TERM")) {
//Panel_mensajes.MostrarMensaje("CLIENTE " + server.getInetAddress().toString().replace("/", "") + " DICE -> " + line + "\n");
//proto.entrada(line);
this.responderPeticiones(line);
if(!ACTIVO) break;
}
this.responderPeticiones("\n" + "CONEXION TERMINADA: " + server.getInetAddress().toString().replace("/", ""));
Panel_mensajes.MostrarMensaje("\n" + "CONEXION TERMINADA: " + server.getInetAddress().toString().replace("/", "") + "\n" + "\n");
server.close();
} catch (IOException ioe) {
Panel_mensajes.MostrarMensaje("\nIOException AL RECIBIR PETICION: " + ioe.getMessage());
//ioe.printStackTrace();
}
}
//Se encarga de responder peticiones a los clientes
public void responderPeticiones(String s) throws IOException
{
String input = s;
String direccion = server.getInetAddress().toString().replace("/", "");
out.write("SERVIDOR DICE A " + direccion + " -> " + input + "\n");
out.flush();
}
public static void TerminarConexion()
{
ACTIVO = false;
proto = null;
}
}
(I didn’t add the Panel_mensajes class, because is not much relevant)
It’s not easy to understand your code (I guess it’s portuguese or spanish). The problem seems to be in
EjecutarServidor, you have 3 static attributes:If a new client connects you simply reset the reference to the client former socket by:
This may not work when several clients connect concurrently as the reference to
socketmay break betweenand
Defining
listeneras a static attribute is definitely not a good practive, but should work given your samples. But defining the staticsocketis definitely an error and may lead to unexpected results. You should move theSocketdeclaration intoEjecutarServidor.ejecutar()like:Fix this and see if it changes your app’s behaviour.