Sockets   zodpovězená otázka

C#, I/O operace

Zdravím všichni,

už nějakou chvilku si pohrávám s programováním ve VB .Net (hraju si momentálně s Visual Basic 2008 Express), ale rozhodně nejsem žádný guru. Spis bych se označil jako "bastlič-drátotah", jak kdysi vcelku trefně poznamenal jeden můj kolega.

Inu nastala jednoho dne potřeba zbavit se tohoto cejchu a pozvednout moje programátorství na úroveň alespoň začátečník. Řekl jsem si, že aplikace typu klient-datábaze (řekl bych první krůčky v životě začínajícího programátora, jako jeden ze základů jeho působení) můzu nesměle označit, jako povětšinou zvládnuté a s chutí se vrhnout do světa větších a působivějších úkolů.

Co může být pro programátora mého "formátu" větší výzvou, než spojit dohromady dva pocitace po síti a donutit je poslat si mezi sebou data. Co takhle soubor? Ne, to je pro začátek moc najednou. Co takhle nějaký string? ... aspoň písmenko?

Našel jsem si na netu pár příkladů jak na to a nadšeně se vrhnul do víru tcpClientu a tcpListeneru. Světe div se, komunikace se asi na stotisící pokus povedla. Moje nadseni neznalo konce. Památná věta "MÁMO, ONO TO NA MĚ PÍPLO!" dostala nových rozměrů. Ono to totiž píplo když já jsem chtěl a ne, kdyz nějaká tajemná AI (řekl bych spíš nějaký zašitý sadistický šotek) si zrovna vzpomněla, ze je potřeba uživatele dostatečně zprudit neznámou hláškou s tajemným obsahem.

Mno, abych se nepřechválil, šotek si stejne ke mně našel cestu a zchladil moje nadšení hluboko pod bod mrazu. Ja vím, moc kecám a málo píšu k věci, tak se vrhnu primo k jádru pudla.

Mám server aplikaci, která poslouchá na portu 7761 a čeká na příchozi spojeni. Vypada to nějak takhle:

 Sub startListening()

        Dim tcpL As New TcpListener(7761)
        Dim tcpC As New TcpClient
        Dim netStream As NetworkStream
        Dim msg As String

        tcpL.Start()

        Do Until False

            tcpC = tcpL.AcceptTcpClient()
            netStream = tcpC.GetStream

            Dim recStream(10024) As Byte
            Dim buffLen As Integer = CInt(tcpC.ReceiveBufferSize)

            Try
                netStream.Read(recStream, 0, buffLen)
            Catch ex As SocketException
                If ex.NativeErrorCode = 10054 Then
                    MsgBox("Client down")
                End If
            End Try

            msg = Encoding.ASCII.GetString(recStream)

            If msg <> "" And Not msg Is Nothing Then
                MsgBox(msg)
            End If

        Loop
    End Sub

pustím k práci klienta, který pošle malou zprávu:

 Sub sendMsg(ByVal msg As String)

        Dim tcpC As New TcpClient
        tcpC.Connect(System.Net.IPAddress.Parse("192.168.1.1"), 7761)
        netStream = tcpC.GetStream

        Dim sendData As Byte() = Encoding.ASCII.GetBytes(msg)
        netStream.Write(sendData, 0, sendData.Length)
        netStream.Flush()

        tcpC.Close()

    End Sub

vše proběhne jak má, zpráva se odešle, server přijme a zobrazí. Svět je krásný. Ale problém nastane, když klienta vypnu. Server se začne cítit osaměle a uzemní mě hláškou: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

Ošetření chyby je jedna věc. Try - Catch - End Try udělá své. Ale v tomto případě ne. Vůbec nedojde na zachycení chyby a serverová aplikace rovnou padá.

Mohli by jste mi prosím poradit s tím, jak správně ukončit klienta, nebo jak správně zachytit chybu na serveru, abych dokázal říct: Tak klient už své řekl, víc nechce, tak je off?

Díky za jakoukoliv pomoc

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

Bylo by dobré naučit klienta, aby se se serverem rozloučil. To znamená že než se od něj odpojí, pošle mu nějáký předem definovaný příkaz (v tom stringu který posíláte). Server podle něj pozná co mu chce klient říct (v tomto případě to, že už mu nic dalšího říct nechce) a patřičně na to zareaguje.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

to by šlo, ale co v případě, že se z nějakého důvodu násilně přeruší spojení? Nefunkční síť, padne počítač a pod.?

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

Ano to se samozřejmě stát může. Pro tento případ je potřeba chybu odchytit a zareagovat stejně, jako když se klient odpojí standartně. Sice píšete že to žádnou vyjímku nevyhodí, ale to se mi něják nezdá. Neodchytáváte to na špatném místě?

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

Aha, tak jsem zjistil, kde je problém.

Chybu jsem odchytával, ale špatně.

použil jsem: Catch ex As SocketException a ten chybu neodchytí. Je potřeba použít Catch ex As Exception. Důvod proč jsem chtěl použít SocketException byl ten, že jsem chtěl odchytit i ErrorCode, který v "normálním" Exception není. Bohužel to bude muset jít jinak.

Každopádně moc díky za ten nápad s rozloučením.

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

a tento kod vam funguje aj na dialku ak nezadate ip 192.168.1.1 ale napriklad cudziu ip 77.88.154.22 ??

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

Jak jsem psal na začátku, je to moje první aplikace se sockets, ale hádám, že by to mělo fungovat). Je to normální komunikace přes TCP. Jenom bude potřeba brát v potaz firewally, routery, proxy servery a podobně. Další otázkou bude bezpečnost ... ale to už bude asi úplně někde jinde, než s tím mým mini kódem.

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

No .. nefunguje , neviem naco su potom sockety a cele TCP vo VB.NET ked mi nejde sa spojit na dialku a este ktomu mi stale vyskakuju okna o tom ze dana aplikacia chce komunikovat so vzdialenym pc a pritom pri pripojeni na iny system vyhodi chybu xD ...

Zlate ICQ zaujimalo by ma co maju oni v zdrojovom kode ze im tak hladko vsetko ide :/...

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Už měsíc vám tu všichni vysvětlují, že chyba je v tom, že absolutně nechápete, jak TCP/IP funguje. ICQ funguje proto, že máněkde centrální servery s veřejnou IP a komunikuje se přes ně. Pokud nemáte alespoň na jednom konci veřejnou IP adresu, tak se prostě nespojíte, ani kdybyste se rozkrájel.

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

Ve vašem případě je celý problém mezi klávesnicí a židlí.

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