我正在开发一个正在开发的套接字服务器。
首先,套接字服务器遵循类:
班级Main_Servidor
(执行服务器)
类EjecutarServidor
(基本上等待新连接,然后将它们作为子流程运行)
类ManejoConexion
(从home接收套接字对象,并在套接字中写入和读取)
类Panel_mensajes
(显示有关jpanel
中的套接字连接的信息)
客户端是用adobe air编写的一个小程序
问题是当连接两个或更多客户端时,只有最后连接的客户端才能读取套接字。我已经使用eclipse的调试器逐步检查,但我找不到错误。
这是我的代码:
Main_Servidor类:
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类:
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课程:
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;
}
}
(我没有添加Panel_mensajes
类,因为没有多大关系)
答案 0 :(得分:2)
在ManejoConexion
类中,您有3个不应该是的静态变量。尤其是PrintWriter
,它将被设置为LAST实例的Socket输出流,因此第一个实例将突然开始与最后一个实例进行通信。
实际上,我不确定proto
和ACTIVO
的用途,但out
静态变量绝对不应该是静态的。
答案 1 :(得分:1)
理解你的代码并不容易(我猜它是葡萄牙语或西班牙语)。问题似乎在EjecutarServidor
,你有3个静态属性:
private static ServerSocket listener;
private static Socket socket;
private static Boolean EsperarConexiones
如果新客户端连接,您只需通过以下方式重置对客户端套接字的引用:
socket = null;
socket = listener.accept();
当多个客户端同时连接时,这可能不起作用,因为socket
的引用可能会在
socket = listener.accept();
和
ManejoConexion con_nva = new ManejoConexion(socket);
将listener
定义为静态属性绝对不是一个好的方法,但应该可以根据您的样本进行操作。但定义静态socket
肯定是一个错误,可能会导致意外的结果。您应该将Socket
声明移至EjecutarServidor.ejecutar()
,如:
while(EsperarConexiones){
Socket socket = listener.accept(); //<-- fix HERE
Panel_mensajes.MostrarMensaje("NUEVA CONEXION " +
socket.getInetAddress().toString().replace("/", "") + ":"
+ socket.getPort() + ", "
+ fecha.getTime() + "\n" + "\n"
);
ManejoConexion con_nva = new ManejoConexion(socket);
iniciarThread.execute(con_nva);
}
修复此问题,看看它是否会改变您应用的行为。
答案 2 :(得分:-1)
注意ManejoConexion中的private static PrintWriter out;
- 它不应该是静态的。