Pracujeme s protokolem HTTP

Tomáš Herceg       02.02.2008       HTTP/HTML       25031 zobrazení

Protokol HTTP se používá v Internetu na každém kroku. Často jej potřebujeme využívat i z našich aplikací, např. k odeslání nějakých dat na server anebo ke stažení nějaké stránky či souboru s informacemi. V tomto článku si ukážeme základy použití tříd HttpWebRequest a HttpWebResponse, které jsou pro práci s protokolem HTTP určeny.

HTTP (HyperText Transfer Protocol) je internetový protokol navržený původně pro přenášení dokumentů ve formátu HTML. Přestože se dnes tento protokol používá hlavně pro přenášení webových stránek, velmi často se také využívá i pro přenášení jiných dat, např. souborů, obrázků. Protokol je laicky řečeno jazyk, kterým komunikuje webový prohlížeč se serverem. V tomto článku se podíváme, jak tento protokol funguje, a hlavně jak jej používat z prostředí VB.NET, protože to se nám může velmi často hodit.

Jak HTTP funguje?

Nehodlám zde popisovat přesně všechny detaily protokolu HTTP, od toho je specifikace a navíc by to vydalo na několik článků. Záměrně spoustu věcí zjednoduším a vysvětlím jen nezbytné minimum, které by měl znát každý.

Pokud napíšete do webového prohlížeče adresu http://www.vbnet.cz, začne poměrně složitý proces, jehož výsledkem je to, že se vám po chvíli zobrazí náš web. Jak to ale funguje přesně?

  1. Prohlížeč si zjistí IP adresu serveru vbnet.cz a připojí se k tomuto serveru na port 80 pomocí TCP/IP spojení.
  2. Jakmile je spojení vytvořeno, prohlížeč zašle serveru požadavek (request), ve kterém řekne, kterou stránku by chtěl, a prozradí o sobě pár údajů, jako třeba verzi prohlížeče, verzi a jazyk operačního systému a pár dalších věcí.
  3. Server požadavek zpracuje a pošle HTML kód úvodní stránky našeho serveru.
  4. Prohlížeč stránku stáhne a zjistí, že pro kompletní zobrazení bude potřebovat ještě nějaké obrázky, soubor CSS se styly, nějaké soubory s javascriptem atd., o které si zažádá úplně stejně jako o úvodní stránku.
  5. Jakmile server všechna požadovaná data zašle, prohlížeč konečně zobrazí úvodní stránku.

I tento seznam je velmi zjednodušený, ale nám bude prozatím stačit. Existují 3 verze protokolu HTTP, a to verze 0.9, verze 1.0 a verze 1.1, která se používá nejčastěji. My si přesnější princip ukážeme na verzi 1.1, uvidíme, jak komunikace pomocí HTTP funguje.

Když se můj prohlížeč připojí k serveru vbnet.cz, zašle mu přibližně takovýto požadavek (některé hlavičky jsem vymazal):

GET / HTTP/1.1
Host: vbnet.cz
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; Media Center PC 5.0; .NET CLR 3.5.21022)
Proxy-Connection: Keep-Alive

Důležitý je první řádek, na kterém vidíme příkaz GET, dále adresu, kterou chceme získat (v našem případě jen lomítko, které značí úvodní stránku; kdybychom chtěli obrázek, musíme napsat třeba images/star.gif) a nakonec verzi protokolu HTTP/1.1. Na dalších řádcích jsou hlavičky, které prozrazují o prohlížeči nějaké další informace. Celý požadavek končí dvěma konci řádku (pro ukončení řádku se používá sekvence znaků 13 a 10, ve VB.NET to je konstanta vbCrLf).

Server tento požadavek přečte a vrátí následující odpověď (response):

HTTP/1.1 200 OK
Cache-Control: private
Date: Sat, 02 Feb 2008 10:56:17 GMT
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Set-Cookie: Stats=LastDisplayed=Sat, 02 Feb 2008 11:56:17 GMT; expires=Mon, 03-Mar-2008 10:56:17 GMT; path=/
Set-Cookie: menuState=; expires=Sun, 02-Mar-2008 10:56:17 GMT; path=/
Content-Length: 53124

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
...

Na prvním řádku je stavový kód 200, které značí, že je vše v pořádku. Obecně platí čím větší číslo, tím větší průšvih. Pokud číslo začíná dvojkou, je většinou vše v pořádku, pokud začíná trojkou, znamená to, že stránka existuje, ale je někde jined (přesměrování), pokud začíná číslicí 4, je to problém, protože stránka neexistuje nebo k ní nemáme oprávnění. Pokud kód chyby začíná číslem 5, znamená to nějakou chybu na serveru. Za kódem chyby je i krátký popis.

Pak následuje spousta hlaviček, které nám prozradí informace o serveru, dobu platnosti stránky, použité kódování a případně kompresi, a dále třeba počet bajtů kódu stránky. Za hlavičkami jsou opět dvě ukončení řádku a pak již následují samotná data.

Jak stáhnout soubor ve VB.NET jednoduše

Jistě jste už někdy potřebovali v aplikaci stáhnout nějak soubor z Internetu přes HTTP. Teď již zhruba víte, jak protokol HTTP funguje, takže byste mohli vzít třídu TcpClient, napsat připojení k serveru na port 80, sestavit ručně HTTP request, poslat jej a pak si z odpovědi vytáhnout požadovaná data. Vzhledem k tomu, že HTTP se používá opravdu hojně, je logické, že pokaždé psát tuto funkcionalitu by nikoho nebavilo a navíc v tom můžete udělat spoustu chyb. Proto .NET framework obsahuje třídy, které použití protokolu HTTP implementují a jejich použití je snazší.

Nejjednodušší metodou je použít metodu DownloadFile. Skvělé, pokud potřebujete stáhnout soubor a uložit jej na disk. Nemáte ale pak možnost zjistit, kolik procent souboru už je staženo, nemůžete stahování přerušit atd. Na jednoduché věci se to ale může hodit:

My.Computer.Network.DownloadFile("http://www.vbnet.cz", "d:\vbnet.html")

Jak stáhnout data z HTTP se vší parádou

Někdy se může hodit stáhnout data, ale neukládat je na disk. Ukládání na disk je často zbytečné a navíc musíte vytvářet dočasné soubory, které byste po sobě měli mazat, což mimo jiné odvádí pozornost od konkrétních problémů, kteréžto vaše aplikace řeší. K tomuto účelu slouží třídy HttpWebRequest a HttpWebResponse, první z nich vystaví a odešle požadavek a vrátí vám druhou, která nese odpověď serveru. Nahoru do souboru přidejte řádek Imports System.Net, všechny třídy totiž patří do tohoto namespace.

        'vystavit požadavek
Dim rq As HttpWebRequest = HttpWebRequest.Create("http://www.vbnet.cz/")

'odeslat jej na server a získat odpověď
Dim rs As HttpWebResponse = rq.GetResponse()

'přečíst stream až do konce
Using sr As New IO.StreamReader(rs.GetResponseStream())
'vypsat odpověď
MsgBox(sr.ReadToEnd())
End Using

'zavřít spojení
rs.Close()

V první části vytvoříme proměnnou typu HttpWebRequest (pozor na ni, nemá konstruktor, takže žádné New, ale přiřadíme do ní výsledek volání metody HttpWebRequest.Create, které předáme požadovanou adresu URL. Proměnné rq můžeme pak ještě nastavovat hlavičky atd., jakmile jsme s tím hotovi (v našem případě jsme žádné hlavičky nepřidávali), zavoláme metodu GetResponse, která odešle požadavek na server a vrátí objekt HttpWebResponse, který nese odpověď serveru.

Z tohoto objektu, který jsme přiřadili do proměnné rs, můžeme zjišťovat opět hodnoty hlaviček, nás však ale hlavně zajímají data požadavku. Ta jsou bohužel k dispozici pouze ve formě datového proudu (stream), který má metody Read a Write pracující pouze s poli bajtů. To se nám příliš nehodí v případě, že pracujeme s textovými daty. Pokud bychom stahovali obrázek s binárními daty, převádění na String je pitomost! My ale textová data máme, takže s němi chceme pracovat trochu na výši. Naštěstí v .NET frameworku existuje třída IO.StreamReader. My jsme ji používali pro čtení ze souborů, ale pokud v konstruktoru místo jména souboru předáme nějaký Stream, umí tato třída číst z tohoto streamu data a převádět je na String. Hodit se nám mohou hlavně metody ReadLine anebo ReadToEnd.

Nakonec je vhodné zavolat metodu Close na objektu HttpWebResponse, abychom ukončili spojení se serverem.

Ukázková aplikace - jak zjistit aktuální kurz dolaru?

Česká národní banka poskytuje na svém webu v textovém formátu aktuální kurzy některých měn, konkrétně na adrese http://www.cnb.cz/cs/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.txt?date=01.02.2008. Důležité je akorát na konci adresy nastavit správné aktuální datum. Pokud si tento odkaz otevřete v prohlížeči, uvidíte, v jakém formátu jsou informace vráceny. Stačí odpověď projít po řádcích a pokud řádek bude začínat znaky USA|, pak už stačí najít poslední znak | v tomto řádku a přečíst data od něj až do konce. Tím získáme aktuální kurz amerického dolaru. Kód by mohl vypadat následovně:

        Dim kurz As Single = 0

'vystavit požadavek na dnešní den
Dim url As String = String.Format("http://www.cnb.cz/cs/financni_trhy/devizovy_trh/kurzy_devizoveho_trhu/denni_kurz.txt?date={0:dd.MM.yyyy}", Now)
Dim rq As HttpWebRequest = HttpWebRequest.Create(url)

'odeslat jej na server a získat odpověď
Dim rs As HttpWebResponse = rq.GetResponse()

'vytvořit StreamReader pro pohodlnou práci
Dim sr As New IO.StreamReader(rs.GetResponseStream())

'projít řádky
While Not sr.EndOfStream
Dim s As String = sr.ReadLine()

'pokud jsme na řádku s dolarem, vytáhnout z něj kurz
If s.StartsWith("USA|") Then
kurz = CDbl(s.Substring(s.LastIndexOf("|") + 1))
End If
End While

'zavřít StreamReader
sr.Close()

'zavřít spojení
rs.Close()

'vypsat aktuální kurz
MsgBox(String.Format("Aktuální kurz: 1 USD = {0:c}", kurz))

Myslím, že kód je bohatě komentovaný, takže jej není třeba nijak složitě vysvětlovat.

Jak odesílat data metodou POST?

V některých případech chceme serveru poskytnout i další informace, aby mohl svoji odpověď upřesnit. Typickým příkladem jsou stránky s nějakými formulářovými prvky. Data, která jsme do formuláře vyplnili, je nutné nějak dostat na server. Používají se 2 metody - metoda GET, ve které se data zakomponují přímo do adresy URL (www.server.com/stranka.aspx?parametr1=hodnota1&parametr2=hodnota2...), anebo se data odešlou metodou POST. Metodu GET zvládnete jistě sami, postup je úplně stejný, jediné, co musíte upravit, je právě adresa URL.

Pokud chceme odesílat formulář metodou POST, musíme ještě před odesláním požadavku poslat serveru příslušná data. Představme si, že v naší stránce máme tento formulář:

<p>Jméno: <input type="text" name="jmeno" /><br />
Příjmení: <input type="text" name="prijmeni" /><br />
<input type="submit" name="odeslat" value="Odeslat" />

Tato stránka vypadá nějak takto:

Jednoduchý formulář

Pokud chceme odeslat vyplněný formulář na server (např. jméno Tomáš a příjmení Herceg), pak se uvnitř HTTP protokolu použije příkaz POST. Odpověď bude vypadat prakticky stejně, až na vrácená data, ale request bude začínat řádkem POST url HTTP/1.1 a po několika hlavičkách a dvojnásobném konci řádku budou následovat samotná data. Aby server věděl, kdy už data končí, měli bychom mu poslat též hlavičku Content-Length: počet bajtů. Data budou vypadat takto:

jmeno=Tomáš&prijmeni=Herceg&odeslat=Odeslat

Pokud hodnoty obsahují nějaké speciální znaky, měly by se prohnat funkcí URLEncode, kterou najdete v knihovně System.Web (musíte ji ve vlastnostech projektu na záložce References přidat do seznamu). Tato metoda je k nalezení uvnitř třídy HttpUtility. Jak tedy odeslat tento fiktivní formulář, to vidíme zde:

        'vystavit požadavek na dnešní den
Dim rq As HttpWebRequest = HttpWebRequest.Create("http://www.server.com/")

'sestavit data
Dim data As String = "jmeno=" & Web.HttpUtility.UrlEncode("Tomáš") & "&prijmeni=Herceg&odeslat=Odeslat"
Dim bytes() As Byte = System.Text.Encoding.ASCII.GetBytes(data) 'převést data na bajty v kódování ASCII

'poslat je na server
rq.Method = "POST" 'nastavit metodu POST
rq.ContentLength = bytes.Length 'nastavit Content-Length na počet bajtů dat
rq.GetRequestStream().Write(bytes, 0, bytes.Length) 'zapsat data do streamu

'odeslat jej na server a získat odpověď
Dim rs As HttpWebResponse = rq.GetResponse()

'dále s odpovědí pracujeme jako normálně

Data formuláře, která si sestavíme, zapíšeme metodou Write do streamu požadavku, který získáme metodou GetRequestStream. Musíme nastavit vlastnost ContentLength na počet bajtů a také vlastnost Method na hodnotu POST, jinak nám objekt HttpWebRequest ani nedovolí do streamu zapisovat. Pak již jen získáme odpověď a pracujeme s ní jako obvykle.

Závěrem

Tento článek je jenom krátkým vhledem do problematiky. Je dobré vědět, jak protokol HTTP funguje uvnitř, ale je zbytečné psát funkcionalitu HTTP vždy od píky. Lepší je použít standardní řešení, které nám aplikaci neudělá složitou a nepřehlednou.

 

hodnocení článku

5 bodů / 5 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Mohlo by vás také zajímat

Začínáme s ASP.NET - díl 7.: Pokročilá práce s daty, vzhled a témata

V tomto díle seriálu o ASP.NET dokončíme naši aplikaci z minula, ukážeme si, jak editovat záznamy přímo uvnitř komponenty GridView, a kromě dalších nových poznatků si povíme něco málo o rozšiřitelnosti ASP.NET. Napíšeme si totiž vlastní BoundField, který v režimu editace bude hlídat, aby uživatel neodeslal zpět prázdné pole.

Silverlight 2 úvod

Zajímá vás psaní webových aplikací na straně klienta ve vašem oblíbeném nástroji v .NETu? Slyšeli jste o Silverlightu a chcete vědět jak funguje a jestli může pro vás být užitečný? Nebo jen máte zájem poznat možnosti nové webové technologie?

Veřejný kurz PhoneGap – 22. - 23. 1. 2015

 

 

Nový příspěvek

 

Diskuse: Pracujeme s protokolem HTTP

Dobrý den

chcel by som z linkov ktoré vyhľadá google extrahovať url aby som v nich mohol vyhľadať cenu podľa zadanej položky.

a neviem s tým pohnúť ďalej. vyhadzuje mi iba nazvy tlačítok.

Private Sub WebBrowser1_Documentdownload(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserNavigatedEventArgs) Handles WebBrowser1.Navigated

Dim adres As String = String.Empty

Dim olink As HtmlElement

Dim olinks As HtmlElementCollection = WebBrowser1.Document.Links

For Each olink In olinks

adres = olink.InnerText

MsgBox(adres)

Next

'Dim strHTML = GetPageHTML(adres)

End Sub

Public Function GetPageHTML(ByVal URL As String) As String

' Retrieves the HTML from the specified URL

Dim objWC As New System.Net.WebClient()

Return New System.Text.UTF8Encoding().GetString( _

objWC.DownloadData(URL))

End Function

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

Diskuse: Pracujeme s protokolem HTTP

Dobrý den,

mám (jako VB-začátečník) problém: Vytvořím prvky web-formuláře ve skriptu. Po spuštění uživatel vyplní, odešle. Tím se znovu načte aspx, ale logicky si nepamatuje data. Chci vědět, co uživatel zadal a podle toho chci jinak sestrojit formulář (nechci použít jiný aspx s natvrdo definovaným obsahem).

Jenže data formuláře vytvořená dynamicky jsou známá až po vytvoření polí a hlavně přidání do formuláře (form1.Controls.Add(xxx)) - na rozdíl od tvrdě definovaných. A to je pozdě!

1) Opětovné vymazání prvků má problémy a je to "programová špína"

2) Napadlo mě načíst proměnné něším podobným jao $_POST v PHP. Asi je to ve VB pomocí WebClient, HttpWebRequest ap.

** Prosím, jaký postup zvolit. Budu vděčný za každý příklad, tip ap. !!! Díky moc Radek

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

Použitelné jsou oba způsoby:

1) Opětovné mazání prvků není žádná špína a dělá se to, je to naprosto korektní postup. Fungují takhle spousta ASP.NET komponent - např. GridView. Při načtení stránky si vygeneruje nějakou sadu řádků a pokud uživatel klikne na tlačítko v řádku, GridView musí nejdřív vygenerovat přesně to, co ve stránce měl, aby se mu vyvolaly události atd. Jakmile zjistí, co se stalo, smaže ten záznam, smaže vygenerované řádky a vytvoří je znovu.

2) I tohle je možné, ale nemá to nic společného s WebClientem nebo HttpWebRequestem.

V ASP.NET máte objekt HttpContext.Current, který vždy reprezentuje aktuální HTTP požadavek. Ten drží objekt Request, Response atd.

Hodnoty parametrů odeslaných metodou POST získáte přes HttpContext.Current.Request.Form["param"].

Pokud jste ve stránce, stačí jen Request.Form["param"] - stránka definuje vlastnost Request, která vrací Request z aktuálního HttpContext, pro zkrácení zápisu.

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

Vážený Tomáši,

nesmírně Vám děkuji!! Zabralo to!! Po několika dnech civění do stroje, střídání euforií z drobných nadějí a zoufalství, lezení po internetu celého světa ... jsem nakonec získal řešení v domácí kotlině... když se to zná, jke to jednoduché :-)

Prosím ještě o doporučení: jsem začátečník ve stádiu kukly a zjišťuji, že se bez oficielního základu, pojmů ap., ve světě VB neobejdu a vše stojí neadekvátní množství času.

Máte prosím nějaké doporučení na literaturu, weby ap., které by mi můj sen splnily? Ještě jednou velké díky!! Radek

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

Literaturu moc nesleduji, takže nevím, jestli jsem schopen nějakou doporučit.

Hodně materiálů najdete přímo na tomto webu, výborným zdrojem je též web http://www.aspnet.cz.

Veškeré své materiály o ASP.NET jsem dal na web http://www.webforms.cz.

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

Moc děkuji! A přeji hodně zdaru!

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

Diskuse: Pracujeme s protokolem HTTP

Ahoj.

Posílám text metodou POST a mám problém s UrlEncode.

Dim data As String = "xxx=" & Web.HttpUtility.UrlEncode(dlg.TextBox1.Text)

Píše to chybu HttpUtility is not a member of Web.

System.Web mám importovaný. Už nevím co s tím.

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

Co u Vás znamená to dlg před textboxem?

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

Musíte nareferencovat celou knihovnu System.Web způsobem

My project > References > Add reference > najít v seznamu System.Web

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

Diskuse: Pracujeme s protokolem HTTP

Je možné oerať niečo ako :|jeden|(dva)[tri]

aby to vytiahlo všetko okrem toho ||()[] a samostatne každé slovo ktoré bolo ohraničené napísalo každé do iného riadku ?

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

Pročte si kapitolu Práce s textem a řetězci.

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

Diskuse: Pracujeme s protokolem HTTP

Dobrý den,

mám následující hrubý kod:

********************

Dim webPozadavek As httpWebRequest

Dim webOdpoved As httpWebResponse

Dim s As FileStream

dim encode as Encoding = System.Text.Encoding.GetEncoding("utf-8")

dim strreader as StreamReader

webPozadavek=WebRequest.Create(AdresaServeru)

With webPozadavek

.Method="POST"

.Headers.Add("vystup","txt")

.Headers.Add("oddelovac","strednik")

.Headers.Add("rozsah","vse")

.Headers.Add("odeslano","true")

End With

webOdpoved=webPozadavek.GetResponse

strreader=New streamreader(webOdpoved.GetResponseStream,encode)

Clipboard.SetText(strreader.ReadToEnd)

*********************

V podstatě jde o to, že se mi do schránky při běhu programu uloží obsah html stránky, kdežto prohlížeč mi nabídne uložení csv souboru. A já se potřebuji dostat k csv souboru, abych s nim mohl dale pracovat.

Můžete mi prosím poradit, kde najdu to, co server vrací a není to html, ale csv soubor?

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

xxx

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

xxx

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

xxx

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

Diskuse: Pracujeme s protokolem HTTP

Dobry den

Prosim Vas o pomoc v orezani casti textu. Z clanku som vytiahol kod :

 Dim sr As New IO.StreamReader(rs.GetResponseStream())
         'projít řádky
         While Not sr.EndOfStream
             Dim s As String = sr.ReadLine()
             'pokud jsme na řádku s dolarem, vytáhnout z něj kurz
             If s.StartsWith("USA|") Then
                 kurz = CDbl(s.Substring(s.LastIndexOf("|") + 1))
             End If
         End While

kod funguje v poriadku ale iba pri requeste , ale ja pouzivam Net.WebClient teda :

Dim msgcache As String
Client1.DownloadString( URL , msgcache ) 

'a ked skusim msgcache.readline napise chybu ze invalid path teda program hlada asi cestu k suboru a potreboval by som nieco ako readstringline viete mi pomoct ?

mam program na chat cez moj FTP server a pri stahovani spravy z FTP by som chcel aby zobrazil iba text pod riadkom v ktorom je napisane _MSG teda by to malo vyzerat takto :

_HEADER01

uzivatel001 'toto je meno uzivatela

_MSG

ahoj 'toto je sprava a je potrebne aby z celeho textu odstranil vyzsi text (_HEADER atd.) a zobrazil iba riadok s ahoj

Predom Dakujem za pomoc :) K.Moser

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

Diskuse: Pracujeme s protokolem HTTP

Zdravím, nevíte někdo, jak mužů odeslat stránku, s argumenty podobnými jako jmeno=Tomas&prijmeni=Herceg&odeslat=Odeslat, když není uvedeno jméno tlačítka ve zdrojovém kódu stránky? Díky

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

Použij Fiddler2. Je to výborný nástroj, zejména v režimu Inspectors - Raw. Přesně vidíš, co si se serverem povídá tvůj prohlížeč a potom to "jen" napíšeš tak, aby ti to samý dělal program.

Dalibor

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

Předpokládám tedy, že na ten web máš oficiální přístup a že nemáš v plánu nějaký DOS útok - popření služby a nebo že se nechceš na na ten server hacknout. Jestli jo, tak na mou radu zapomeň. Nic jsem ti neřekl. ( Dostanou tě )

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

Diskuse: Pracujeme s protokolem HTTP

Prosím Vás, Dobří lidé. Nevíte náhodou, proč mi My.Computer.Network.DownloadFile hází velice nahodile při stahování z FTP chybu: Během požadavku WebClient došlo k výjimce . V režimu ladění mi to neudělalo tuším nikdy, když ale pustím hotovej exáč, tak to dělá. Obecně to dělá tím častěji, čím více je stroj na kterým to běží zatíženej. Například i přítomnost antiviru (AVG9) na to má vliv. Je-li přítomno, dělá to častěji. Ale k chybě dojde i bez AVG. Jakoby, když se ten stroj dostane do týhle schýzy, tak to dělá i při opakovaných pokusech několikrát zasebou. Pak to přestane a zase např. několik dnů je pokoj. Nebo mi někdo doporučíte na stahování z FTP něco jiného ? Prohledal jsem všechno možné a vypadá to, že se na webech a diskusích tahle chyba frameworku nevyskytuje, asi jsem první. Nechápu, mě to dělá všude. Firewallem to není.

Děkuji Mnohokrát

Dalibor

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

Podařilo se mi to vyprovokovat i v režimu ladění a tohle jsem z toho vyčetl:

WebException was unhandled

{"Během požadavku WebClient došlo k výjimce."}

{Name = "WebClient" FullName = "System.Net.WebClient"}

InnterException Operace na soketu nemohla být provedena, protože systém neměl dostatečný prostor ve vyrovnávací paměti nebo protože byla plná fronta

SocketErrorCode System.Net.Sockets.SocketError.NoBufferSpaceAvailable (No free buffer space is available for a Socket operation.)

StackTrace v System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)

v System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

Jak se prosím ten buffer nastavuje ?

Jestli je tu některý z Tomášů, prosím, i jestli nevíte, krátce písněte. Díky Moc.

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

Tohle může být způsobeno čímkoliv. Buď to blokuje antivirák, protože se domnívá, že tolik už aplikace vytváří mnoho spojení, nebo je to Windows. Nevytváříte pro stažení každého souboru nového WebClienta? To by mohlo sedět. Chtělo by to používat starého.

Pokud k tomu dochází náhodně a nepředvídatelně, pak se to bude obecně špatně hledat, ale zkuste se opravdu podívat, jestli vytváříte víc WebClientů, nebo jenom jednoho. Pokud jen jednoho, tak je to nějaké divné.

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

Díky Moc, tak jsem to zjednodušil, dělá to i takhle (místo xxx login a heslo) :

Module Module1
    Sub Main()
        Try
            My.Computer.Network.DownloadFile("ftp://62.24.89.244/test", "C:\pokus\test", "xxx", "xxx", False, 100000, True)
        Catch ex As Exception
            Console.WriteLine(ex.Message)
            Console.WriteLine(ex.InnerException)
        End Try
        Console.ReadLine()
    End Sub
End Module

Dělá mi to na WinXP, i bez antiviru, i s vypnutým firewallem.

Na to ftp mám 20Mbps připojení, asi to bude tím, na vzdálenější ftp mi to neudělalo. Našel jsem na to tohle:

http://msdn.microsoft.com/en-us/library/...

Ale prostě to neumím implementovat. Tak jak je to napsaný mi to prostě nebere, hlásí, že objekt není nastaven na bázi objektu. Má se to prý nějak psát ponovu... nevím. Přiznávám se, že tady mám mezery. Takhle to tam píšou:

Public Property ReceiveBufferSize As Integer

Dim instance As TcpClient

Dim value As Integer

value = instance.ReceiveBufferSize

instance.ReceiveBufferSize = value

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

Tady je kompletní podrobná chybová zpráva:

System.Net.WebException was unhandled

Message="Během požadavku WebClient došlo k výjimce."

Source="System"

StackTrace:

v System.Net.WebClient.DownloadFile(Uri address, String fileName)

v Microsoft.VisualBasic.MyServices.Internal.WebClientCopy.DownloadFile(Uri address, String destinationFileName)

v Microsoft.VisualBasic.Devices.Network.DownloadFile(Uri address, String destinationFileName, ICredentials networkCredentials, Boolean showUI, Int32 connectionTimeout, Boolean overwrite, UICancelOption onUserCancel)

v Microsoft.VisualBasic.Devices.Network.DownloadFile(String address, String destinationFileName, String userName, String password, Boolean showUI, Int32 connectionTimeout, Boolean overwrite, UICancelOption onUserCancel)

v Microsoft.VisualBasic.Devices.Network.DownloadFile(String address, String destinationFileName, String userName, String password, Boolean showUI, Int32 connectionTimeout, Boolean overwrite)

v ConsoleApplication1.Module1.Main() v C:\Documents and Settings\kontrola\Dokumenty\Visual Studio 2008\Projects\Pokusy\Pokusy\Module1.vb:řádek 27

v System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)

v System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)

v Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()

v System.Threading.ThreadHelper.ThreadStart_Context(Object state)

v System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)

v System.Threading.ThreadHelper.ThreadStart()

InnerException: System.IO.IOException

Message="Nelze číst data z přenosového připojení: Operace na soketu nemohla být provedena, protože systém neměl dostatečný prostor ve vyrovnávací paměti nebo protože byla plná fronta."

Source="System"

StackTrace:

v System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

v System.Net.FtpDataStream.Read(Byte[] buffer, Int32 offset, Int32 size)

v System.Net.WebClient.DownloadBitsState.SetResponse(WebResponse response)

v System.Net.WebClient.DownloadBits(WebRequest request, Stream writeStream, CompletionDelegate completionDelegate, AsyncOperation asyncOp)

v System.Net.WebClient.DownloadFile(Uri address, String fileName)

InnerException: System.Net.Sockets.SocketException

ErrorCode=10055

Message="Operace na soketu nemohla být provedena, protože systém neměl dostatečný prostor ve vyrovnávací paměti nebo protože byla plná fronta"

NativeErrorCode=10055

Source="System"

StackTrace:

v System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)

v System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

InnerException:

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

Když to napíšu takhle, tak to funguje spolehlivě a stahuje rychleji:

            Dim output As FileStream
            Dim ftpreq As FtpWebRequest

            Dim ftpresp As FtpWebResponse
            Dim stream As Stream

            Dim buffer1(512) As Byte
            Dim intRead As Int32 = 1

            output = New FileStream("C:\pokus\test2.txt", FileMode.Create)
            ftpreq = FtpWebRequest.Create(New Uri("ftp://ftpserver/test"))

            ftpreq.Method = WebRequestMethods.Ftp.DownloadFile
            ftpreq.Credentials = New NetworkCredential("user", "passw")

            ftpresp = ftpreq.GetResponse()
            stream = ftpresp.GetResponseStream()

            Do While Not intRead = 0
                intRead = stream.Read(buffer1, 0, buffer1.Length)
                output.Write(buffer1, 0, intRead)
            Loop

            stream.Close()
            output.Close()
            ftpresp.Close()

Takže asi zůstanu u klasických requestů, protože My.Computer.Network.DownloadFile na stahování z FTP asi nebude zrovna ideální. Kdyby ale někdo náhodou věděl, jak se nastavuje ten buffer, určitě to rád vyzkouším. Na druhou stranu, kdyby někdo věděl, že je to zbytečná práce a že to stejně nepomůže, tak budu také rád, dá-li echo.

Ahoj, díky všem, Dalibor.

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

Ještě naposledy se vrátím k tomu mýmu problému s použitím My.Computer.Network.DownloadFile na stahování z FTP. Házelo to nahodile hlavně při spuštění více aplikací chybu Během požadavku WebClient došlo k výjimce.

Problém vyřešilo nastavení optimalizace přidělování paměti - pro aplikace. Původně bylo - pro mezipaměť systému, protože jsem pracoval na stroji, který je zároveň SQL serverem + na něm běží spousty dalších procesů. Po přenastavení jsem nezpozoroval žádné vážné snížení výkonu SQL serveru, takže považuji věc za uzavřenou. Takže na nastavení optimalizace přidělování paměti pozor. Když to není přímo nutné, asi lépe nechat optimalizaci pro aplikace.

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

Diskuse: Pracujeme s protokolem HTTP

Pokud máte xp a nižší tak si to mušete vyskoušet na terminálu.

XP:

START>Všechny Programy>Příslušenství>Komunikace>HyperTerminal

V okénku připojit dejte localhost a port co chcete (16bitové bezznaménkové číslo - existuje tedy 65535 portů), zapněte prohlížeč (nejede mi MSIE 6), v terminálu vyskočí že localhost není možné připojit k 3556 tak dejte ok, nahoře v nabídce zavolat dejte čekat na volání a nakonec dejte do prohlížeče adresu "http://localhost:(port co jste si vybrali)" a v terminálu vám to vyskočí. Potom se můžete zachovat jako server a dát tomu nějákou fiktivní odpověď :-).

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

Diskuse: Pracujeme s protokolem HTTP

V ukazce jste odeslal jmeno a prijmeni metodou POST. Jak by se ale meli uchovat tyto informace pro dalsi pouziti jestli by je chtel pozdeji server od nas precist formou cookies?

Respektive, jak pozadavek servru o jejich vytvoreni odchytit z odpovedi servru po odeslani jmena a prijmeni.

(Omlouvam se pokud to pisu krkolome, ale snad pochopite o co mi jde. Dekuji)

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

Diskuse: Pracujeme s protokolem HTTP

zdravim, mohol by som sa opytat, ze akym systemom si mozem prezriet request, ktory je odosielany serveru z mojej aplikacie. je to pisane vo VB.NET.

ked dam totiz:

Dim request As HttpWebRequest

request = CType(WebRequest.Create("http://nieco.sk/Default.aspx"), HttpWebRequest)

request.ContentType = "application/x-www-form-urlencoded"

request.Method = "POST"

request.AllowAutoRedirect = False

Dim srd As New StreamReader(request.GetRequestStream())

dostanem chybu: Stream was not readable.

viem ze by som mal citat responsestream (to dokazem), ale ja si chcem pozriet aj requeststream a tam to pada

diki moc za radu

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

Diskuse: Pracujeme s protokolem HTTP

mam otazku aky je prosim vas kod nato aby som ziskal informacie z webu, lebo ako je hore uvedene na priklade kde si ziskava kurz dolara http://www.cnb.cz/cs/financni_trhy/deviz...{0:dd.MM.yyyy} tak tato adresa poukazuje na web ktory NEMA html kod. Ale ja potrebujem ziskat informacie z webu napr. z webu http://ozene.zoznam.sk/se/100299/Slnecne... a z tej stranky potrebujem dany horoskop. a teraz neviem ako to mam spravit lebo nechce mi to vobec ist :(

Dakujem.

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

ja mam podobnej problem, ja potrebujem spravit program ktory by mi kontroloval stav bodu na MegaUpload.com, ale problem je ze neviem tiez ako to spravit, kedze sa tam nenachadza API tak ako na RapidShare :( prosim poradte ako mam najst text v nejakom subore (myslim tak ze mam nejaky dokument a v nom hladat nejaky text)

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

Ahoj, na vyhledávaní části textu se výbroně hodí regulární výrazy a já je velmi často využívám. Informace např. zde www.regularnivyrazy.info

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

a nemohol by si mi najako to vysvetlit alebo spravit ukazku ako spravim ze pouzijem ten regex a na stranke mu najde UserName: a vyhodi mi to do Msgbox ? plz

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

a nemohol by si mi najako to vysvetlit alebo spravit ukazku ako spravim ze pouzijem ten regex a na stranke mu najde UserName: a vyhodi mi to do Msgbox ? plz

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

Hotové řešení vám tady nikdo dělat nebude, nemáme na to čas. V tomto článku máte podrobně vysvětleno, jak se dá stáhnout soubor z Internetu, a v následujícím článku máte velmi pěkně vysvětleno, jak pomocí regulárního výrazu najít to, co chcete. Jen nesmíte být líný se něco naučit a oba články si přečíst.

http://www.vbnet.cz/clanek--122-regularn...

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

Diskuse: Pracujeme s protokolem HTTP

mam otaku k comu sluzi {0:c} alebo aka je jebo presna definicia v programe. Lebo este len zacinam s programovanim a ked vidim na priklade : MsgBox(String.Format("Aktuální kurz: 1 USD = {0:c}", kurz)) tak za = je ten dany zmieneny kod. Co to teda vlasne znamena a preco to tma musi byt.

Dakujem

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

Tzv formátovací řetězec, v tomhle případě to znamená, že za {0:c} se má dát druhý parametr (první je ten format string, proto tam je 0) a c znamená, že to má vytisknout jako měnu (currency). Více na http://msdn.microsoft.com/en-us/library/...

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

Diskuse: Pracujeme s protokolem HTTP

Laboroval jsem s posíláním dat přes POST na script v php na Apache serveru. Nějak to nefungovalo, jelikož php script neměl naplněno pole $_POST .

Vyřešilo to přidání následujícího :

rq.ContentType = "application/x-www-form-urlencoded"

Chci se jen zeptat. Co tímto do hlavičky vlasně přidávám ? (nejswm hlavičkový odborník a ani se jím nechci stát :-) )

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

Diskuse: Pracujeme s protokolem HTTP

uváděli jste:

My.Computer.Network.DownloadFile("http://www.vbnet.cz", "d:\vbnet.html")

To vše je dobré, ale málo komu se ta stránka uloží na cédéčko... ;-)

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

A podle tebe mají všichni pod písmenkem D cédéčkovou mechaniku? Seděl jsi někdy u PC, které má víc disků (nebo diskových oddílů)? ;-)

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

a vy jste někdy seděl/la u počítače z klávesnicí nebo programem klávesnice na obrazovce

asi ne

nebo jste tak líný/líná že nekliknete nestisknete 2 tlačítka a máte to?

je to dobrá ukázka

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

Hele bráchno když chceš tak můžeš dát třeba příkaz NET USE Z: http://vnet.cz/images a potom se ti v tento počítač ukazuje složka na netu. Takhle to já dělám a nepotřebuju FTP klienta. Jinak by jsem potřeboval helpa (je mi 14 a s VB začínám) u jednoho programu mám update system. Stáhne soubor programu a pak ho spustí. Potřeboval bych to s progressbarem. Už dva dny googlim a nemůžu na to přijít. Myslel jsem, že bych moh dostat procenta pro progressbar tim, že by jsem vydělil celkovou velikost souboru tim, co jsem už stáh a vynásobil 100, ale newim jak získat velikost souboru na FTpéčku...Předem děkuji za rady.

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

Diskuse: Pracujeme s protokolem HTTP

Potřeboval bych stáhnout z internetu obrázek a zobrazit v PictureBoxu (nemusel by se ani ukládat do složky s programem).

Už samotný uložení je pro mě problém :-(

Pomůžete mi?

Díky za případný odpovědi :)

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

Diskuse: Pracujeme s protokolem HTTP

Potřebuji se přihlásit (poslat data metodou POST) na server, který ale začíná https://... a přihlašuji se přes SSL. Pokud napíši výše zmíněný kód tak se zvýrazní tento řádek:

rq.GetRequestStream().Write(bytes, 0, bytes.Length)

a u toho chybové hlášení:

WebException was unhandled

The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.

Můžeš mi, prosím, poradit co s tím? Díky

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

To jsem zase já, ještě bych to upřesnil, potřeboval bych vlastně, aby to udělalo to stejné jako kdybych byl na té stránce, zadal uživatelské jméno a heslo a klikl na odeslat, tzn. aby se i ulozily cookies. Díky za odpověď Mephisto

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

Nazdar, mám takový problém. Dělám php a učím se pracovat s připojením a HTTP dotazy. Nemám žádnou knížku a ne netu sem nic nenašel. Ale dochází mi nervy. Vždycky možu načíst jen hlavní stranu serveru. Ale když do políčka HOST: napíšu za tu doménu třeba /index.php tak to hned píše, že sem poslal špatný dotaz. Tak jak to mám teda napsat? Díky za odpověď a omlouvám se za zdržování

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

Do HOST: se píše jen název serveru, ne adresa URL. Ta se píše za příkaz GET nebo POST.

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

Diskuse: Pracujeme s protokolem HTTP

Díky za články, chtěl sem se zeptat,a HttpWebRequest, muj visual basic 2005 jej nezná :( možná sem nějak nepřidal class nebo nevím, prostě ten příkaz nezná :(

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

Ale ovšem že zná, jenom musíte pořádně číst. Úplně nahoru do souboru s kódem musíte přidat řádek:

Imports System.Net

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

Diskuse: Pracujeme s protokolem HTTP

Jde nějak ošetřit situace, kdy na kompu není internet? Teď se to totiž zacyklí... Nešlo by třeba vypsat že není spojení?

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

Nezacyklí, jenom to čeká, než vyprší časový limit spojení, což je asi 10 nebo 30 sekund. Můžete provést např. tento test:

If Not My.Computer.Network.IsAvailable Then
    MsgBox ("Nejste připojeni k Internetu")
End If

Tím zjistíte, jestli je počítač připojen k nějaké síti.

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

Pravda, ale těch 30 sekund se ta aplikace jakoby zasekne a vůbec nereaguje, zkoušel jsem to vyřešit aly se to zjišťoalo v jiném vláknu, ale nakonec jsem nastavil timeout na 3 sekundy a vypršení ošetřil vyjmkou, kde vypíšu, že se nepodařilo spojení.

Jinak ten tvůj test na síť se moc nedá využít, protože testuje jakoukoliv síť...

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

Diskuse: Pracujeme s protokolem HTTP

Hezky clanek o hezke tride; akorat jsi zapomel na posilani souboru, coz je vec, s cimz jsem stravil jedno odpoledne (nez jsem prisel na to, jak spravne formatovat POST request a ze apache na linuxu proste nesezere 25 souboru najednou i kdyz me testovaci windowsacke na localhostu jo) a i kdyz jsem to nejak zflikoval pomoci studia referenciho manualu k HTTP, tak by me zajimalo, jak se to dela poradne a ciste pomoci .net trid.

A taky bych mel poznamku:

Kdyz neco posilas pres POST a pouzivas ten RequestStream, tak neni od veci si ho nejdriv dat do promenne a pak ho zavrit nebo aspon Flushnout, jinak to muze delat problemy (a me delalo).

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

Na posílání souborů jsem nezapomněl, je to trochu složitější. Pokud bych ten RequestStream používal na více řádcích, tak bych jej určitě do proměnné dal. Asi by bylo lepší zavolat na něj ještě Flush, přidám to do článku.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • 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