我只是想从 Java 上的服务器和 android 上的客户端建立连接。我的问题是我创建了一个线程等待消息在 EditText 上打印。我只收到从服务器发送的第一条消息,就像默认消息一样,说“连接成功”现在,当我发送第二条消息时,应用程序刚刚关闭,我必须强制关闭。我确定问题出在我拥有方法 leermensajes() 的线程上。我不知道该怎么做,现在我是 Android 的新手,而且我也没有太多的编程经验。
这是客户端代码
public class ClienteActivity extends Activity {
/** Called when the activity is first created. */
private ObjectOutputStream salida;
private ObjectInputStream entrada;
private String mensaje = "";
private String servidorChat;
private int puerto;
private Socket cliente;
private CheckBox check;
private Button boton;
private EditText mensajeservidor;
private AutoCompleteTextView text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Componentes graficos
//Intento dar una accion a un boton
boton = (Button) findViewById(R.id.button1);
check = (CheckBox) findViewById(R.id.checkBox1);
text = (AutoCompleteTextView) findViewById(R.id.textBox);
mensajeservidor = (EditText)findViewById(R.id.editText1);
servidorChat = "151.57.15.160"; // servidor
puerto = 12345; // puerto
try {
cliente = new Socket( servidorChat , puerto );
salida = new ObjectOutputStream( cliente.getOutputStream() );
salida.flush();
entrada = new ObjectInputStream( cliente.getInputStream() );
//entrada = new ObjectInputStream( cliente.getInputStream() );
leermensajes();
//mensaje = ( String ) entrada.readObject();
//CharSequence cs = mensaje;
//mensajeservidor.setText(cs);
}
catch ( EOFException excepcionEOF ) {
Toast.makeText(ClienteActivity.this,"El cliente termino la conexion",Toast.LENGTH_LONG).show();
}
catch (UnknownHostException e) {
//Alert que avisa del error
Toast.makeText(ClienteActivity.this, R.string.UnkowHost,Toast.LENGTH_LONG).show();
android.util.Log.w("¡¡¡ERROR!!!", e.getMessage());
} catch (IOException e) {
Toast.makeText(ClienteActivity.this, R.string.ConectionError,Toast.LENGTH_LONG).show();
android.util.Log.w("¡¡¡ERROR!!!", e.getMessage());
}
}
protected void onDestroy() {
try {
salida.close();
cliente.close();
} catch (IOException e) {
Toast.makeText(ClienteActivity.this, R.string.errorDesconexion,Toast.LENGTH_LONG).show();
android.util.Log.w("¡¡¡ERROR!!!", e.getMessage());
}
super.onDestroy();
}
public void onEnviarClick(View button1) {
try {
if (cliente != null) {
salida.writeObject("CLIENTE>>>"+text.getText().toString());
salida.flush(); // vacíar búfer de salida para enviar
// información de encabezado
} else
Toast.makeText(ClienteActivity.this, R.string.ConectionError,Toast.LENGTH_LONG).show();
} catch (UnknownHostException e) {
Toast.makeText(ClienteActivity.this, R.string.UnkowHost,Toast.LENGTH_LONG).show();
android.util.Log.w("¡¡¡ERROR!!!", e.getMessage());
} catch (IOException e) {
Toast.makeText(ClienteActivity.this, R.string.ConectionError,Toast.LENGTH_LONG).show();
android.util.Log.w("¡¡¡ERROR!!!", e.getMessage());
}
}
public void onConectarDesconectar(View checkBox) {
if (!check.isChecked()) {
boton.setEnabled(false);
text.setEnabled(false);
} else {
boton.setEnabled(true);
text.setEnabled(true);
}
}
public void leermensajes(){
new Thread(new Runnable(){
public synchronized void stop(){
cliente = null;
salida = null;
entrada = null;
}
public void run() {
try {
entrada = new ObjectInputStream( cliente.getInputStream() );
mensaje = ( String ) entrada.readObject();
while (true){
CharSequence cs = mensaje;
mensajeservidor.setText(cs);
}
}
catch ( EOFException excepcionEOF ) {
Toast.makeText(ClienteActivity.this,"El cliente termino la conexion",Toast.LENGTH_LONG).show();
}
catch (UnknownHostException e) {
// //Alert que avisa del error
Toast.makeText(ClienteActivity.this, R.string.UnkowHost,Toast.LENGTH_LONG).show();
android.util.Log.w("¡¡¡ERROR!!!", e.getMessage());
} catch (IOException e) {
Toast.makeText(ClienteActivity.this, R.string.ConectionError,Toast.LENGTH_LONG).show();
android.util.Log.w("¡¡¡ERROR!!!", e.getMessage());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
stop();
}
}).start();
}
}
这是服务器代码,但效果很好
public Servidor()
{
super( "Servidor" );
Container contenedor = getContentPane();
// crear campoIntroducir y registrar componente de escucha
campoIntroducir = new JTextField();
campoIntroducir.setEditable( false );
campoIntroducir.addActionListener(
new ActionListener() {
// enviar mensaje al cliente
public void actionPerformed( ActionEvent evento )
{
enviarDatos( evento.getActionCommand() );
campoIntroducir.setText( "" );
}
}
);
contenedor.add( campoIntroducir, BorderLayout.NORTH );
// crear areaPantalla
areaPantalla = new JTextArea();
contenedor.add( new JScrollPane( areaPantalla ),
BorderLayout.CENTER );
setSize( 300, 150 );
setVisible( true );
} // fin del constructor de Servidor
// configurar y ejecutar el servidor
public void ejecutarServidor()
{
// configurar servidor para que reciba conexiones; procesar las conexiones
try {
// Paso 1: crear un objeto ServerSocket.
servidor = new ServerSocket( 12345, 100 );
while ( true ) {
try {
esperarConexion(); // Paso 2: esperar una conexión.
obtenerFlujos(); // Paso 3: obtener flujos de entrada y salida.
procesarConexion(); // Paso 4: procesar la conexión.
}
// procesar excepción EOFException cuando el cliente cierre la conexión
catch ( EOFException excepcionEOF ) {
System.err.println( "El servidor terminó la conexión" );
}
finally {
cerrarConexion(); // Paso 5: cerrar la conexión.
++contador;
}
} // fin de instrucción while
} // fin del bloque try
// procesar problemas con E/S
catch ( IOException excepcionES ) {
excepcionES.printStackTrace();
}
} // fin del método ejecutarServidor
// esperar que la conexión llegue, después mostrar información de la conexión
private void esperarConexion() throws IOException
{
mostrarMensaje( "Esperando una conexión\n" );
conexion = servidor.accept(); // permitir al servidor aceptar la conexión
mostrarMensaje( "Conexión " + contador + " recibida de: " +
conexion.getInetAddress().getHostName() );
}
// obtener flujos para enviar y recibir datos
private void obtenerFlujos() throws IOException
{
// establecer flujo de salida para los objetos
salida = new ObjectOutputStream( conexion.getOutputStream() );
salida.flush(); // vaciar búfer de salida para enviar información de encabezado
// establecer flujo de entrada para los objetos
entrada = new ObjectInputStream( conexion.getInputStream() );
mostrarMensaje( "\nSe recibieron los flujos de E/S\n" );
}
// procesar la conexión con el cliente
private void procesarConexion() throws IOException
{
// enviar mensaje de conexión exitosa al cliente
String mensaje = "Conexión exitosa";
enviarDatos( mensaje );
// habilitar campoIntroducir para que el usuario del servidor pueda enviar mensajes
establecerCampoTextoEditable( true );
do { // procesar los mensajes enviados por el cliente
// leer el mensaje y mostrarlo en pantalla
try {
mensaje = ( String ) entrada.readObject();
mostrarMensaje( "\n" + mensaje );
}
// atrapar problemas que pueden ocurrir al tratar de leer del cliente
catch ( ClassNotFoundException excepcionClaseNoEncontrada ) {
mostrarMensaje( "\nSe recibió un tipo de objeto desconocido" );
}
} while ( !mensaje.equals( "CLIENTE>>> TERMINAR" ) );
} // fin del método procesarConexion
// cerrar flujos y socket
private void cerrarConexion()
{
mostrarMensaje( "\nFinalizando la conexión\n" );
establecerCampoTextoEditable( false ); // deshabilitar campoIntroducir
try {
salida.close();
entrada.close();
conexion.close();
}
catch( IOException excepcionES ) {
excepcionES.printStackTrace();
}
}
// enviar mensaje al cliente
private void enviarDatos( String mensaje )
{
// enviar objeto al cliente
try {
salida.writeObject( "SERVIDOR>>> " + mensaje );
salida.flush();
mostrarMensaje( "\nSERVIDOR>>> " + mensaje );
}
// procesar problemas que pueden ocurrir al enviar el objeto
catch ( IOException excepcionES ) {
areaPantalla.append( "\nError al escribir objeto" );
}
}
// método utilitario que es llamado desde otros subprocesos para manipular a
// areaPantalla en el subproceso despachador de eventos
private void mostrarMensaje( final String mensajeAMostrar )
{
// mostrar mensaje del subproceso de ejecución despachador de eventos
SwingUtilities.invokeLater(
new Runnable() { // clase interna para asegurar que la GUI se actualice apropiadamente
public void run() // actualiza areaPantalla
{
areaPantalla.append( mensajeAMostrar );
areaPantalla.setCaretPosition(
areaPantalla.getText().length() );
}
} // fin de la clase interna
); // fin de la llamada a SwingUtilities.invokeLater
}
// método utilitario que es llamado desde otros subprocesos para manipular a
// campoIntroducir en el subproceso despachador de eventos
private void establecerCampoTextoEditable( final boolean editable )
{
// mostrar mensaje del subproceso de ejecución despachador de eventos
SwingUtilities.invokeLater(
new Runnable() { // clase interna para asegurar que la GUI se actualice apropiadamente
public void run() // establece la capacidad de modificar a campoIntroducir
{
campoIntroducir.setEditable( editable );
}
} // fin de la clase interna
); // fin de la llamada a SwingUtilities.invokeLater
}
public static void main( String args[] )
{
JFrame.setDefaultLookAndFeelDecorated(true);
Servidor aplicacion = new Servidor();
aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
aplicacion.ejecutarServidor();
}
} // fin de la clase Servidor