Newsgroup: it.comp.java
Titolo: Socket: situazione disperata!

Sto cercando di prendere confidenza con la classe Socket. Tutto quello
che vorrei realizzare č
un semplice programmino client-server che funzioni nel seguente modo:
1) il server si mette in attesa della connessione
2) il client richiede la connessione e il server l'accetta
3) il server recapita un messaggio al client ("Ciao client!")
4) il client passa al server il contenuto di un file, che lo salva su
disco a sua volta
5) una volta ricevuto il file, il server manda un altro messaggio al
client ("File ricevuto!")
6) il client stampa il messaggio ricevuto dal servere e esce
7) il server esce
Ecco il codice. Il problema č descritto nei commenti: scusate se sono
in maiuscolo, ma in
minuscolo ci sarebbe stato ancora piů casino
// AppClient.java
import java.net.*;
import java.io.*;
public class AppClient {
  public static void main(String[] args) throws IOException {
    InetAddress addr = InetAddress.getByName("localhost");
    System.out.println("addr = " + addr);
    Socket socket = new Socket(addr, 8081);
    try { System.out.println("socket = " + socket);
      BufferedReader in = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
      BufferedOutputStream out = new
BufferedOutputStream(socket.getOutputStream());
   // RICEZIONE E STAMPA PRIMO MESSAGGIO DAL SERVER: TUTTO OK
      String s = in.readLine();
      System.out.println("il server dice: " + s);
   // INVIO DATI AL SERVER
      byte b[] = Mu.fileToByteArray("plainText.txt"); // mio metodo
      ByteArrayInputStream is = new ByteArrayInputStream(b);
      out.write(b, 0, b.length); // VEDI CODICE Server.java
      out.flush();
   /*
   // CASO 1:
   // COSI' IL CLIENT TERMINA PRIMA CHE IL SERVER POSSA INVIARE IL
MESSAGGIO
   // "File ricevuto!" LA STRINGA s  RIMANE UGUALE A "" E NON VIENE
STAMPATA
      s = in.readLine();
      System.out.println("il server dice: " + s);
   */
   // CASO 2:
   // PROVO A RIMANERE IN ATTESA DI UNA STRINGA DAL SERVER CHE SIA
DIVERSA DA ""
   // NE IL SERVER NE IL CLIENT TERMINANO: IL CLIENT RIMANE BLOCCATO
   // SU s = in.readLine(), MENTRE IL SERVER, RIMANE
_INSPIEGABILMENTE_ BLOCCATO
   // SULLA WHILE CHE HO SEGNATO SOTTO NEL CODICE DI Server.java
      while (true) {
        s = in.readLine();
        if (!s.equals("")) {
          System.out.println("il server dice: " + s);
          break;
        }
      }
    } finally {
      System.out.println("chiudo");
      socket.close();
      System.exit(0);
    }
  }
}
// Server.java
import java.io.*;
import java.net.*;
public class Server {
  public static void main(String[] args) throws IOException {
    ServerSocket s = new ServerSocket(8081);
    System.out.println("Server partito: " + s);
    try { Socket socket = s.accept();
      try {
        System.out.println("Connessione al socket: " + socket);
        PrintWriter outW = new PrintWriter(
          new BufferedWriter(new
OutputStreamWriter(socket.getOutputStream())),true);
        BufferedInputStream in = new
BufferedInputStream(socket.getInputStream());
     //INVIO PRIMO MESSAGGIO: QUESTO ARRIVA AL CLIENT
        outW.println("Ciao client!\r\n");
        outW.flush();
     // RICEZIONE DATI DAL CLIENT E SCRITTURA SU FILE: FIN QUI TUTTO
OK
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        int c = 0;
     // CASO 1: TUTTO OK
     // CASO 2:
     // SE PROVO A FAR RIMANERE IN ASCOLTO IL CLIENT DOPO AVERE
SPEDITO I DATI CON
     // out.write(b, 0, b.length); (VEDI CASO 2 SOPRA) IL SERVER
CONTINUA A
     // CICLARE NELLA WHILE. PERCHE' il -1 NON ARRIVA?
        while ((c = in.read()) != -1)
          byteOut.write(c);
        Mu.byteArrayToFile(byteOut.toByteArray(), "out.txt"); // mio
metedo
     //!!! INVIO DEL SECONDO MESSAGGIO, CHE IN NESSUN CASO ARRIVA AL
CLIENT !!!
        outW.println("File ricevuto!\r\n");
        outW.flush();
      } finally {
        System.out.println("Chiudo");
        socket.close();
      }
    } finally {
      s.close();
      System.exit(0);
    }
  }
}
Spero sia tutto chiaro.
Ho come l'impressione che il problema sia una sciocchezza incredibile,
ma non riesco a
capirlo!
Grazie in anticipo per l'attenzione, ciao!
GePs


Ho dato un occhiata un po' superficiale e forse bisognerebbe analizzare
anche i metodi byteArrayToFile e fileToByteArray, ma, comunque, se credi che
il problema sia il mancato ricevimento del carattere -1, perché non provi ad
inviarlo esplicitamente dal client alla fine dell'invio del file?
In questo modo saresti sicuro che il -1 viene spedito, il server lo riceve e
quindi dovrebbe terminare la connessione in modo corretto.
Saluti.
Luciano.

...

Non credo che i problemi siano nei due metodi, comunque te li posto
più sotto (sono da migliorare, però funzionano). Ho provato anche a
mandare il -1, ma quando il client si punta sul secondo in.readLine()
si blocca tutto...
	public static byte[] fileToByteArray(String fn) {
		byte[] b = null;
		try {
			Vector v = new Vector();
			DataInputStream in =
				new DataInputStream(
					new BufferedInputStream(
						new FileInputStream(fn)));
			int size = 0;
			while (in.available() != 0) {
				v.add(new Byte(in.readByte())); 
				size++;
			}
			Byte[] B = new Byte[v.size()];
			Enumeration enum = v.elements();
			int i = 0;
			while (enum.hasMoreElements())
				B[i++] = (Byte)enum.nextElement();
			b = new byte[B.length];
			for (int j = 0; j < b.length; j++) {
				b[j] = B[j].byteValue();
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			return b;
		}
	}
 
	public static void byteArrayToFile(byte[] data, String fn) {
		try {
			FileOutputStream fos = new FileOutputStream(fn);
			fos.write(data);
			fos.close();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
	}

Ciao ragazzi!
Colgo questo post per per porre anche un mio problema!:D (Invece che
risolverlo eh?!:D)
No dai... a parte gli scherzi... anche io sto cercando di prendere
confidenza con i socket e con i flussi di input e di output.
Per gli esperimenti che ho fatto mi sono sempre trovato bene con la
classe ObjectInputStream e ObjectOutputStream.
In questo caso potresti spedire la stringa di benvenuto dal server (
vedere dal client se è una istanza di una stringa ( visto che mi
sembra sia considerata come un oggetto in java) e successivamente fare
la stessa cosa con un oggetto file)
Potrebbe essere una soluzione no?
Ora però arriva il mio problema... fino ad ora ho sempre utilizzato le
classi che ho citato sopra, nn sentendo mai la necessità di usare le
altre... quando si utilizzano?

Ti posto il Server e il Client modificati e funzionanti.
import java.net.*;
import java.io.*;
public class Client {
public static void main(String[] args) throws IOException {
     InetAddress addr = InetAddress.getByName("localhost");
     System.out.println("addr = " + addr);
     Socket socket = new Socket(addr, 8081);
     try { System.out.println("socket = " + socket);
       BufferedReader in = new BufferedReader(new
 InputStreamReader(socket.getInputStream()));
     DataOutputStream out = new
 DataOutputStream(socket.getOutputStream());
    // RICEZIONE E STAMPA PRIMO MESSAGGIO DAL SERVER: TUTTO OK
       String s = in.readLine();
       System.out.println("il server dice: " + s);
    // INVIO DATI AL SERVER
       byte b[] = Mu.fileToByteArray("plainText.txt"); // mio metodo
//       ByteArrayInputStream is = new ByteArrayInputStream(b);
  for (int i=0; i< b.length; i++)
   out.write(b[i]);
  out.write(-1);
       //out.write(b, 0, b.length); // VEDI CODICE Server.java
       //out.flush();
    /*
    // CASO 1:
    // COSI' IL CLIENT TERMINA PRIMA CHE IL SERVER POSSA INVIARE IL
 MESSAGGIO
    // "File ricevuto!" LA STRINGA s  RIMANE UGUALE A "" E NON VIENE
 STAMPATA
       s = in.readLine();
       System.out.println("il server dice: " + s);
    */
    // CASO 2:
    // PROVO A RIMANERE IN ATTESA DI UNA STRINGA DAL SERVER CHE SIA DIVERSA
DA ""
    // NE IL SERVER NE IL CLIENT TERMINANO: IL CLIENT RIMANE BLOCCATO
    // SU s = in.readLine(), MENTRE IL SERVER, RIMANE INSPIEGABILMENTE_
BLOCCATO
    // SULLA WHILE CHE HO SEGNATO SOTTO NEL CODICE DI Server.java
       while (true) {
         s = in.readLine();
         if (!s.equals("")) {
           System.out.println("il server dice: " + s);
           break;
         }
       }
     } finally {
       System.out.println("chiudo");
       socket.close();
       System.exit(0);
     }
   }
 }
 // Server.java
 import java.io.*;
 import java.net.*;
 public class Server {
   public static void main(String[] args) throws IOException {
     ServerSocket s = new ServerSocket(8081);
     System.out.println("Server partito: " + s);
     try { Socket socket = s.accept();
       try {
         System.out.println("Connessione al socket: " + socket);
         PrintWriter outW = new PrintWriter(
           new BufferedWriter(new
 OutputStreamWriter(socket.getOutputStream())),true);
         DataInputStream in = new
 DataInputStream(socket.getInputStream());
      //INVIO PRIMO MESSAGGIO: QUESTO ARRIVA AL CLIENT
         outW.println("Ciao client!\r\n");
         outW.flush();
      // RICEZIONE DATI DAL CLIENT E SCRITTURA SU FILE: FIN QUI TUTTO OK
         ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
         byte c = 0;
      // CASO 1: TUTTO OK
      // CASO 2:
      // SE PROVO A FAR RIMANERE IN ASCOLTO IL CLIENT DOPO AVERE SPEDITO I
DATI CON
      // out.write(b, 0, b.length); (VEDI CASO 2 SOPRA) IL SERVER CONTINUA A
      // CICLARE NELLA WHILE. PERCHE' il -1 NON ARRIVA?
         while ((c = in.readByte()) != -1)
           byteOut.write(c);
         Mu.byteArrayToFile(byteOut.toByteArray(), "out.txt");
           // mio metodo
      //!!! INVIO DEL SECONDO MESSAGGIO, CHE IN NESSUN CASO ARRIVA AL CLIENT


 Ti posto il Server e il Client modificati e funzionanti.
Grazie! :)