2012-10-28 14 views
5

Ho creato un client in Java e voglio semplicemente inviare alcuni dati al mio server che è in C#.Client/Server App - Perdere byte

Il problema è che se scrivo nel client ad esempio ciao, ottengo solo la prima lettera. Nell'array di byte c'è solo un elemento.

Credo che ci sia qualche problema con il lato server perché nel mio server in JAVA funziona tutto bene in modo che il cliente in JAVA funziona bene.

Qualcuno vede qualche problema?

Grazie in anticipo.

+1

Hai eseguito il debug per scoprire se k è> 1? –

+0

K = 1. Se ottengo il risultato corretto, dovrebbe essere il numero di elementi presenti nell'array di byte. Ma poiché esiste un solo elemento, k = 1. – Kubik

+0

Provare a svuotare il flusso di output dopo aver inviato i dati. –

risposta

2

il problema si verifica in modo analogo sul lato java perché l'ascoltatore funziona correttamente. Ho copiato il codice del listener in un'applicazione di test. Poi ho creato un'altra applicazione di test e ho inviato la parola Ciao e l'ho ascoltata completamente.

public static void sender() 
{ 
    TcpClient client = new TcpClient(); 
    IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("192.168.2.236"), 30000); 
    client.Connect(serverEndPoint); 
    NetworkStream clientStream = client.GetStream(); 
    ASCIIEncoding encoder = new ASCIIEncoding(); 
    byte[] buffer = encoder.GetBytes("Hello Server!"); 

    clientStream.Write(buffer, 0, buffer.Length); 
    clientStream.Flush(); 
} 


Connection accepted from 192.168.2.236:22811 
Recieved... 
Hello Server! 

Btw, questo potrebbe essere migliore ascoltatore.

public void listener() 
    { 
    TcpListener tcpListener = new TcpListener(IPAddress.Any, 30000); 
    tcpListener.Start(); 

    TcpClient tcpClient = tcpListener.AcceptTcpClient(); 
    NetworkStream clientStream = tcpClient.GetStream(); 

    byte[] message = new byte[4096]; 
    int bytesRead; 

    while (true) 
    { 
    bytesRead = 0; 

    try 
    { 
     //blocks until a client sends a message 
     bytesRead = clientStream.Read(message, 0, 4096); 
    } 
    catch 
    { 
     //a socket error has occured 
     break; 
    } 

    if (bytesRead == 0) 
    { 
     //the client has disconnected from the server 
     break; 
    } 

    //message has successfully been received 
    ASCIIEncoding encoder = new ASCIIEncoding(); 
    Console.Write(encoder.GetString(message, 0, bytesRead)); 
    } 

    tcpClient.Close(); 
} 
+0

Grazie! Questo ascoltatore funziona. Anche se ancora non capisco perché il precedente non l'abbia fatto. – Kubik

3

Stai pensando a TCP nel modo sbagliato, non semplicemente "ricevere" una volta e ottenere il risultato di una "Invia".

TCP è un protocollo "streaming" e non si separa automaticamente in "pacchetti". Potresti anche ottenere dati di 2 mandate in una ricezione.

Un modello comune è quello di anteporre un messaggio con la sua lunghezza, in modo da poter chiamare ricevere fino ad ottenere la quantità di byte richiesti. Per rendere la ricezione restituisce immediatamente se nessun dato è nel buffer, set your socket to non-blocking.

Here's another good article on the topic.

Ora, il codice fornito dovrebbe funzionare in entrambi i casi perché non v'è accanto a nessuna latenza su reti locali. Hai controllato se i tuoi buffer delle parti Java sono a vapore/puoi scaricarli manualmente?

3

Come ha detto Damon Gant, TCP è un protocollo di streaming. Ti suggerisco di creare il tuo protocollo. Non vorrei inviare stringhe. Se stai facendo qualcosa di non banale, questo è davvero il modo migliore per andare.

In genere ho includono un numero magico, checksum, lunghezza del corpo del pacchetto in byte, e la versione del protocollo nei miei intestazioni del protocollo. Il numero magico facilita la delineazione dei pacchetti in un flusso (molto utile per il debug del flusso del protocollo personalizzato). Avere un checksum consente di verificare correttamente le cose. Un checksum non aiuta molto con l'integrità su TCP poiché il protocollo TCP ha già un checksum. La lunghezza del corpo del pacchetto ti aiuta a rilevare quando hai tutti i byte per il tuo pacchetto. La versione del protocollo può aiutarti a capire come interpretare i byte del corpo del pacchetto.

Dopo aver ricevuto i dati, posizionare tutti i byte in un buffer separato e cercare l'intestazione del protocollo. Se è possibile analizzare l'intestazione, verificare che i byte del pacchetto siano tutti presenti. In tal caso, analizzare il pacchetto. Ripeti questo processo finché non trovi un pacchetto incompleto o il buffer è vuoto.

Per ogni pacchetto che si desidera inviare, vorrei creare una classe. Quando si desidera inviare un pacchetto, creare e serializzare la classe appropriata e anteporre l'intestazione del protocollo per i byte di quella classe.

È possibile utilizzare il serializzatore Java, ma se molti client si connettono a un singolo server, probabilmente non si desidera utilizzare Java per il server. Ciò rende le cose difficili perché ora è necessario implementare un serializzatore java in un'altra lingua. Per questo motivo è meglio sia convertire i pacchetti in byte a mano (noiosi ma semplici) OPPURE è possibile scrivere il proprio serializzatore usando il reflection. Suggerirei quest'ultimo per progetti più grandi.

Problemi correlati