2012-10-28 8 views
5

Stworzyłem klienta w Javie i chcę po prostu wysłać trochę danych do mojego serwera, który jest w C#.Aplikacja klienta/serwera - utrata bajtów

Problem polega na tym, że jeśli piszę w kliencie na przykład witam, otrzymuję tylko pierwszą literę. W tablicy bajtów jest tylko jeden element.

Zgaduję, że jest jakiś problem ze stroną serwera, ponieważ na moim serwerze w JAVA wszystko działa dobrze, więc klient w JAVA działa dobrze.

Czy ktoś widzi jakiś problem?

Z góry dziękuję.

+1

Czy debugowania, aby dowiedzieć się, czy k jest> 1? –

+0

K = 1. Jeśli dobrze to pojmuję, powinna to być liczba elementów w tablicy bajtów. Ale ponieważ istnieje tylko jeden element, k = 1. – Kubik

+0

Spróbuj wypróżnić wyjście po wysłaniu danych. –

Odpowiedz

2

Problem jest po stronie Java, ponieważ twój słuchacz działa dobrze. Kopiuję wklejony kod odbiornika w aplikacji testowej. Potem utworzyłem kolejną aplikację testową i wysłałem słowo "cześć" i słuchałem go całkowicie.

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, to może być lepszy słuchacz.

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

Dziękujemy! Ten słuchacz działa. Nawet jeśli nadal nie rozumiem, dlaczego poprzedni nie zrobił. – Kubik

3

Myślisz o TCP w niewłaściwy sposób, nie po prostu "Odbierz" raz i uzyskaj wynik jednego "Wyślij".

TCP to protokół "przesyłania strumieniowego" i nie jest automatycznie dzielony na "pakiety". Możesz nawet otrzymać dane z 2 wysyłek w jednym odebraniu.

Typowy wzorzec to przedrostek jednej wiadomości o jej długości, aby można było wywoływać odbiór do momentu otrzymania żądanej liczby bajtów. Aby natychmiast powrócić do odbioru, jeśli żadne dane nie znajdują się w buforze, set your socket to non-blocking.

Here's another good article on the topic.

Teraz Twój kod powinien działać pod warunkiem, albo sposób, ponieważ nie ma prawie żadnych opóźnień w sieciach lokalnych. Czy sprawdziłeś, czy Twoje bufory części Javy parują/czy możesz je ręcznie przepłukać?

3

Jak powiedział Damon Gant, TCP jest protokołem transmisji strumieniowej. Proponuję utworzyć własny protokół. Nie wysyłałbym strun. Jeśli robisz coś niebanalnego, to jest to naprawdę najlepsza droga.

Zazwyczaj do nagłówków protokołów dołączam magiczną liczbę, sumę kontrolną, długość pakietu w bajtach i wersję protokołu. Magiczna liczba ułatwia definiowanie pakietów w strumieniu (bardzo przydatne do debugowania niestandardowego strumienia protokołu). Posiadanie sumy kontrolnej pomaga zapewnić poprawne analizowanie danych. Suma kontrolna nie pomaga zbytnio w integralności przez TCP, ponieważ protokół TCP ma już sumę kontrolną. Długość ciała pakietu pomaga wykryć, kiedy masz wszystkie bajty dla swojego pakietu. Wersja protokołu może pomóc ci w interpretacji bajtów treści pakietu.

Po otrzymaniu danych umieść wszystkie bajty w osobnym buforze i zeskanuj nagłówek protokołu. Jeśli możesz przeanalizować nagłówek, sprawdź, czy wszystkie bajty pakietu są obecne. Jeśli tak, przeanalizuj pakiet. Powtarzaj ten proces, aż znajdziesz niekompletny pakiet lub bufor jest pusty.

Dla każdego pakietu, który chcesz wysłać, utworzę klasę. Gdy chcesz wysłać pakiet, utwórz i serializuj poprawną klasę i dodaj nagłówek protokołu dla bajtów tej klasy.

Możesz użyć serializatora Java, ale jeśli masz wielu klientów łączących się z jednym serwerem, prawdopodobnie nie chcesz używać Javy dla serwera. To sprawia, że ​​rzeczy są trudne, ponieważ teraz musisz zaimplementować serializator java w innym języku. Z tego powodu zazwyczaj lepiej jest konwertować twoje pakiety do bajtów ręcznie (nużące, ale proste). LUB możesz napisać swój własny serializator za pomocą odbicia. Proponuję to drugie na większe projekty.

Powiązane problemy