Problém se zavřením TCP/IP spojení   zodpovězená otázka

VB.NET, Algoritmy, I/O operace

Zdravím, narazil jsem na problém při uzavírání TCP/IP spojení.

Takže:

-mám jednu aplikaci která beží na PC a naslouchá na určitém portu (pouze naslouchá nic neposílá)

-druhá aplikace beží na mobilu (jen posílá nic nepříjmá)

Pokud se mobilem připojím k PC a spojení zavřu aniž bych předtím odeslal nějáká data, hostitelská aplikace (na PC) na to správně zareaguje. Ale pokud se připojím, odešlu nějáká data a pak chci spojení zavřít (tcp.close) hostitelská aplikace si toho nevšimne.

Ale pokud na mobilu aplikaci ukončím uplně (bez odpojování) hostitelská aplikace na to zase správně zareaguje. Vůbec to nechápu...

Přidávám kód, je to okopírované z kreslící tabule a lehce upravené pro moje potřeby:

    Sub CtiData(ByVal at As System.IAsyncResult)
        Try
            Dim prijato As Integer = networkStream.EndRead(at) ' dokončíme čtení dat a zjistíme kolik dat přišlo 
            If prijato < 1 Then Throw New Exception() ' spojení bylo ukončeno (přichází 0B dat) 

            '============ KOD NA ZPRACOVANI PRICHOZICH DAT ============================
            'text_buffer += System.Text.Encoding.ASCII.GetString(Buffer, 0, prijato)    ' přidání přijatých dat 
            text_buffer += System.Text.Encoding.UTF8.GetString(Buffer, 0, prijato)
            Do While text_buffer.Contains(";") ' dokud máme příkazy, které můžeme parsovat 
                Dim poziceStredniku As Integer = text_buffer.IndexOf(";") ' najdeme ukončovací znak 
                Dim prikaz As String = text_buffer.Substring(0, poziceStredniku) ' přečteme příkaz až ke středníku 
                text_buffer = text_buffer.Substring(poziceStredniku + 1) ' a prikaz odřízneme 
                ProvedPrikaz(prikaz) ' pošleme příkaz ke zpracování 
            Loop
            '=========================================================================

            tcp.GetStream.BeginRead(Buffer, 0, BUFFER_SIZE, AddressOf CtiData, Nothing)          ' přečetli jsme všechny příchozí data, proto budeme čekat až přijdou další 
        Catch e As ObjectDisposedException
            ' proběhlo zrušení spojení 

        Catch e As Exception
            lblStatus.Text = "Spojení ukončeno klientem"    ' informujeme uživatele 
            Me.NotifyIcon1.Text = "Aplikace běží" & vbLf & "Stav aplikace: OFF LINE"
            zalozitSpojeni()

        End Try
    End Sub

Zjistil jsem, že pokud před odpojením odešlu nějáká data, tato procedura vůbec neproběhne.

Klientská část by měla být v pořádku TCP.close se zavolá v obou případech.

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

Tenhle kód je nějaká prasárna. Určovat že proběhlo zrušení spojení na základě vyjímky ObjectDisposedException je hovadina, stejně jako to určovat pomocí vyhození obecné vyjímky Exception, která může nastat z uplně jiného důvodu (např. protože networkStream nebo at bude Nothing). Doporučoval bych použít .NET Remoting, kde jste zcela odstíněn od "low-level" TCP komunikace a použití je naprosto primitivní. A nebo použít k odesílání UDP, což je tzv. Fire-and-Forget, kde není třeba udržovat spojení...

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

To je u TCP/IP trochu problém. Nemáte zaručeno, že si druhá strana ukončení hned všimne. Osobně kombinuji vždy 2 mechanismy:

1) V protokolu by měl existovat příkaz, který informuje o řádném ukončení. Klient nebo server ho před zavřením vždy pošle.

2) Po určitých intervalech neaktivity by měl server posílat příkaz na který bude čekat jednoduchou odpověd (takový ping). Pokud při tomto procesu zpráva nedojde a bude vyvolána vyjímka, tak víme, že spojení bylo přerušeno.

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

Děkuji oběma. Vytvoření příkazu pro odpojení mě také napadlo, ale myslel jsem že uzavření spojení a odeslání příkazu serveru je automatické. U kreslící tabule vše funguje správně a také tam žádný speciální příkaz není.

Vytvořím tedy příkaz a bude klid:)

Přidání timeru a testování zda je spojení OK mě také napadlo ale zase, myslel sem že to je automatické.

Síťovou komunikaci se teprve učím, takže takovéhle školácké chyby jsem čekal:)

Ještě jednou díky.

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

Také bych možná doporučil použít nějakou vyšší vrstvu. Každopádně není na škodu poznat jak to na nízké úrovni funguje a jak se chová a různých prostředích.

A prosím označujte odpovědi.

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