Přenos většího textu   zodpovězená otázka

VB.NET

Dobrý den. Na port jiného počítače bych potřeboval přenést větší množství textu (cca 70283 bajtů to má v txt souboru). Pokud se to snažím poslat pomocí protokolu UDP, tak to řve, že je to větší, než velikost UDP datagramu. Tak teď nevím, jak na to, mám zkusit TCP přenos a nebo ten text rozdělit, poslat přes UDP (tak, jak to dělám u menších textů) a pak na cílovém PC zase sloučit?

Předem děkuji za rady.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Použijte TCP/IP. V UDP je jediná možnost soubor rozdělit, ale tak vzniká šance ztráty nebo rozházení pořadí jednoho nebo více datagramů.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

S TCP protokolem v .NET nemám žádné zkušenosti, zkusím kouknout po příkladech. A TCP je schopen celý balík dat přenést najednou a já nic nemusím kouskovat?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Přečtěte si můj o TCP/IP, je tam chování TCP protokolu popsané:

http://vbnet.cz/serial--5-kreslici_tabul...

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Další možnost by byla použít .NET Remoting (který běží nad TCP protokolem) se kterým se pracuje poměrně jednoduše.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak jsem si jen tak na zkoušku naprogramoval klient a server a dělá mi to divné věci, většinou mi z klienta na server příjde dlouhý text celý, ale stává se, že někdy dorazí jen část.

Klient:

Dim strSendData As String = IO.File.ReadAllText(Application.StartupPath & "\test.xml")
tcp.Connect(RemoteIP, RemotePORT)
Dim networkStream As NetworkStream = tcp.GetStream()
Dim sendBytes As [Byte]() = System.Text.Encoding.ASCII.GetBytes(strSendData)
networkStream.Write(sendBytes, 0, sendBytes.Length)
tcp.Close()

server:

Dim tcpListener As New System.Net.Sockets.TcpListener(43333)
tcpListener.Start()
Dim tcpClient As System.Net.Sockets.TcpClient = tcpListener.AcceptTcpClient()
tcpListener.Stop()
Dim networkStream As System.Net.Sockets.NetworkStream = tcpClient.GetStream()
Dim bytes(256000) As Byte
networkStream.Read(bytes, 0, 256000)
Dim clientdata As String = System.Text.Encoding.ASCII.GetString(bytes)
RichTextBox1.Text = clientdata
tcpClient.Close()
tcpListener.Start()

Co dělám špatně?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Opět Vás odkážu na svůj článek. Zpráva se totiž může rozdělit. Na server přichází postupně a proto musíte sám číst tak dlouho, doku nepřijde celá. Vy čtete jen nárazově první část příchozí zprávy.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

tak proc to nekdy (vetsinou) projde bezproblemu cele a nekdy jen cast?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Protože záleží na řadě okolností - zatížení procesoru, sítě atp. Data se přijímají v jiném vlákně a proto se toho stihne pokaždé jinak. Mohu Vás ještě poprosit, zda nezkusíte psát s diakritikou a dodržovat velká písmena? Přeci jenom tento dialog má posloužit i ostatním.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jasně... takže to předělám tak, že klient si text rozdělí na jednotlivé části a v cyklu jej začne vysílat na server, server začne data přímat a cpát je do stringu a také testovat obsah dat a pokud se v přijatém řetězci bude vyskytovat řetězec obsahující identifikátor konce celého textu, spojení se ukončí. Jen mě zajímá ještě pár věcí... když to začnu vysílat po částech v cyklu, nemůže na serveru dojít k tomu, že něco bude vynecháno z důvodu třeba náhlého vytížení procesoru nějakou jinou aplikací?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

A ještě se chci zeptat, na jak velké části je vhodné posílaný velký XML soubor rozdělit.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak jsem klienta předělal tak, že mi celý velký text posílá po malých částech, ale asi někde dělám něco špatně, protože když si nechám vypsat to, co dostane server, tak se mi vždy vypíše jen ta první část. Asi mám problém na serveru, nevím. Přikládám kód serveru (zjednodušený).

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    ThreadReceive = New System.Threading.Thread(AddressOf ReceiveMessages)
    ThreadReceive.Start()
    ContinueListen = True
End Sub

Sub ReceiveMessages(ByVal at As System.IAsyncResult)
    tcpListener = New System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, 43333)
    tcpListener.Start()
    Do While ContinueListen = True
        tcpClient = tcpListener.AcceptTcpClient
        networkStream = tcpClient.GetStream()
        Dim bytes(1024) As Byte
        networkStream.Read(bytes, 0, 1024)
        Dim clientdata As String = System.Text.Encoding.ASCII.GetString(bytes)
        Debug.Print(clientdata)
        networkStream.Close()
    Loop
End Sub

Prostě to vypíše jen první část, pak, jakoby už přestal přímat data. Koukal jsem na seriál o kreslící tabuli, ale z toho jsem byl jelen.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Poradí někdo prosím?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

V kódu máte chybku, čtete to prostě špatně. Když se podíváte, co se děje, tak je jasné, že vy přečtete 1025 bajtů a pak si NetworkStream zavřete. To samozřejmě není to, co byste chtěl.

Správné čtení ze streamu po kouskách může vypadat třeba takhle:

Dim buffer(1023) As Byte, bytesRead As Integer
Do
    bytesRead = stream.Read(buffer, 0, buffer.Length)
    text &= System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead)
Loop While bytesRead = buffer.Length
stream.Close()

buffer je pole, do kterého se ukládají načítané kousky, metoda Read vrací počet přečtených bajtů. Pokud se načetlo ze streamu méně bajtů, než je délka bufferu, pak jsme už skončili, pokud se načetlo 1024 bajtů, s nejvyšší pravděpodobností budou ještě další data, která máme přečíst.

To, co přečteme, si postupně ukládáme do Stringové proměnné.

Dejte ovšem pozor na kódování češtiny, pokud používáte nějaké windows-1250, bude vše fungovat dobře (akorát místo Encoding.ASCII musíte dát Encoding.Default). Pokud ale máte XML soubor v UTF-8 (anebo kódování není uvedeno, to se pak UTF-8 předpokládá automaticky), vězte, že jeden znak nerovná se 1 bajt. Takže v místě rozdělení 1024 bajtových bloků mohou nastat chyby, jeden znak se rozdělí na dva jiné, které nic neznamenají. Pro práci s UTF-8 daty je lepší celý soubor uložit do jednoho pole (resp. MemoryStreamu) a pak jej teprve převést na finální string, což ale u velkých souborů není příliš vhodné.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback