[C#] Trage overdracht snelheid bij TcpClient

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 11-09 10:19
Hallo,

Ik ben bezig met een eigen usenet reader te ontwikkelen (nee, geen FTD/Spotnet clone) in .NET. Hiervoor gebruik ik mijn .NET componenten, Voor de communicatie met de newsserver (Xsnews, tot 120mbit) maak ik gebruik van de TcpClient class.

Mijn probleem is dat als ik artikelen download van de nieuwsgroepen de snelheid om te janken is. Ik haal met 1 thread max 150kb/s. (Ik weet zeker dat ik een verbinding heb die enkele mbits aankan).

Ik stuur op dit moment alleen het AUTHINFO bericht, GROUP bericht en ARTICLE berichten. Moet ik nog extra andere berichten sturen?

Ik heb geen flauw idee waar het aan kan liggen dat de verbinding zo traag is

Mess with the best, die like the rest


Acties:
  • 0 Henk 'm!

  • bstudio
  • Registratie: Oktober 2007
  • Laatst online: 03-12-2022
Heb je al gekeken naar wat andere newsreaders halen per thread? Dan weet je zeker of het niet aan je verbinding ligt

Acties:
  • 0 Henk 'm!

  • beany
  • Registratie: Juni 2001
  • Laatst online: 17-09 13:56

beany

Meeheheheheh

Laat eens een stukje code zien, en dan voornamelijk je TCP afhandeling thread code?

Dagelijkse stats bronnen: https://x.com/GeneralStaffUA en https://www.facebook.com/GeneralStaff.ua


Acties:
  • 0 Henk 'm!

  • MacWolf
  • Registratie: Januari 2004
  • Laatst online: 06-09-2024
Je kan proberen of de snelheid hoger wordt door gebruik te maken van de WebClient en HttpListener klassen. Als het goed is houdt de WebClient klasse standaard de verbinding in leven, dus er wordt niet elke keer opnieuw verbonden, wat een hoop tijd kost. Wellicht dat daar het probleem zit. Zie: http://stackoverflow.com/...client-have-much-overhead

Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition.


Acties:
  • 0 Henk 'm!

  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 11-09 10:19
beany schreef op woensdag 16 maart 2011 @ 16:58:
Laat eens een stukje code zien, en dan voornamelijk je TCP afhandeling thread code?
Dit is de volledige code die ik gebruik,

De code moet als volgt worden aangeroepen:

- Connect (met je newsserver)
- Authenticate (username en pass) (indien nodig voor je nieuwsserver)
- Switch group zorgt ervoor dat de nieuwsserver weet in welke groep je uithangt, (out parameters meegeven aan GetArticles)
- GetArticles haalt de artikelen daadwerkelijk op en retourneert ze als ID,message.

De reden dat je de outparameters weer aan GetArticles moet meegeven is dat ik van plan ben de articles door meerdere threads te laten downloaden (dus ieder een portie van 100 articles geven).

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
 class NNTPSocket : TcpClient
    {

        private ASCIIEncoding en = new ASCIIEncoding();
        private NetworkStream stream;
        private byte[] buff = new byte[100000];
        ~NNTPSocket()
        {
            Disconnect();
        }

        public bool Connect(string server)
        {
            NoDelay = true;
            Connect(server, 119);
            stream = GetStream();
            string response = Response();
            if ((response.Substring(0, 3) == "200") || (response.Substring(0, 3) == "201"))
            {
                return true;
            }
            return false;
        }

        public bool Authenticate(string username, string password)
        {
            Write("AUTHINFO USER " + username + "\r\n");
            string response = Response();
            if (response.Substring(0, 3) != "381")
            {
                return false;
            }
            Write("AUTHINFO PASS " + password + "\r\n");
            response = Response();
            if (response.Substring(0, 3) != "281")
            {
                return false;
            }
            return true;
        }

        public void Disconnect()
        {            
            Write("QUIT\r\n");
        }

        public bool SwitchGroup(string newsgroup, out long start, out long end)
        {
            Write("GROUP " + newsgroup + "\r\n");
            string response = Response();
            if (response.Substring(0, 3) != "211")
            {
                start = 0;
                end = 0;
                return false;
            }
            string[] values = response.Split(' ');
            start = Int32.Parse(values[2]);
            end = Int32.Parse(values[3]);
            return true;
        }

        public Dictionary<long, string> GetArticles(long start, long end)
        {
            Dictionary<long, string> retval = new Dictionary<long, string>();
            for (long i = start; i < end; i++)
            {
                Write("ARTICLE " + Convert.ToString(i) + "\r\n");
                string article = "";
                bool articleOK = false;
                do
                {
                    string response = Response();
                    if (response.StartsWith("220"))
                    {
                        articleOK = true;                        
                    }
                    article += response;
                    if (response.EndsWith(".\r\n") || response.EndsWith(".\n"))
                    {
                        break;
                    }
                }
                while (articleOK);

                if (articleOK)
                {
                    retval.Add(i, article);
                }
            }
            return retval;
        }

        private void Write(string message)
        {
            byte[] writeBuffer = en.GetBytes(message);
            stream.Write(writeBuffer, 0, writeBuffer.Length);
        }

        private string Response()
        {
            string tempStr = "";
            
            while ((tempStr.Length==0) || (tempStr[tempStr.Length - 1] != '\n'))
            {              
                    int bytes = stream.Read(buff, 0, buff.Length);
                    tempStr += en.GetString(buff, 0, bytes);                
            }
            return tempStr;
        }
    }
bstudio schreef op woensdag 16 maart 2011 @ 16:55:
Heb je al gekeken naar wat andere newsreaders halen per thread? Dan weet je zeker of het niet aan je verbinding ligt
Newsleecher haalt 800kb/s / 1mb/s makkelijk, volgens mij is dit een Delphi applicatie.
MacWolf schreef op woensdag 16 maart 2011 @ 17:22:
Je kan proberen of de snelheid hoger wordt door gebruik te maken van de WebClient en HttpListener klassen. Als het goed is houdt de WebClient klasse standaard de verbinding in leven, dus er wordt niet elke keer opnieuw verbonden, wat een hoop tijd kost. Wellicht dat daar het probleem zit. Zie: http://stackoverflow.com/...client-have-much-overhead
Ik houd de verbinding open gedurende de tijd dat ik articles download (en dus dat ik mijn downloadsnelheid meet) Als ik 1000 articles gedownload heb sluit ik af (wat ik ook terugzie in het netwerkverbruik)

Mess with the best, die like the rest


Acties:
  • 0 Henk 'm!

  • Ventieldopje
  • Registratie: December 2005
  • Laatst online: 17-09 10:59

Ventieldopje

I'm not your pal, mate!

Is je buffer niet wat aan de grote kant? Daar zou je eens mee kunnen spelen.

www.maartendeboer.net
1D X | 5Ds | Zeiss Milvus 25, 50, 85 f/1.4 | Zeiss Otus 55 f/1.4 | Canon 200 f/1.8 | Canon 200 f/2 | Canon 300 f/2.8


Acties:
  • 0 Henk 'm!

  • ThaStealth
  • Registratie: Oktober 2004
  • Laatst online: 11-09 10:19
Volgens mij maakt dit niet veel uit. De tcpbuffer vult het array gewoon totdat zijn eigen buffer leeg is. Op deze manier weet ik dat de hele tcp buffer elke keer gelezen is. Ipv er meeerdere lees acties nodig zijn

Mess with the best, die like the rest


Acties:
  • 0 Henk 'm!

  • TallManNL
  • Registratie: Oktober 2005
  • Laatst online: 17-09 09:11
Wat voor effect heeft een hele korte sleep in je while in je Response. Misschien dat er door minder vaak grotere brokken te lezen een betere performance te halen is.

geheelonthouder met geheugenverlies


Acties:
  • 0 Henk 'm!

  • Contagion
  • Registratie: Maart 2000
  • Laatst online: 14-09 16:26
Zou gebruik van een StringBuilder ipv 'string +=' performance winst opleveren? Je zou ook bij jetbrains even dotTrance kunnen ophalen. Dat is een profiler voor je applicatie zodat je kan zien waar tijd in gaat zitten. Trekt je applicatie bijv ook (een core naar) 100% CPU?

edit: wat de persoon voor mij schrijft zou logisch kunnen zijn. Misschien dat je nu elke keer maar een paar bytes leest omdat die 'while' de hele tijd draait er er op 100% cpu steeds een paar bytes uit de stream worden gepakt. Als je tussendoor even 'sleept' (niet heel mooi, maar goed) dan heeft de buffer tijd zich meer te vullen en dus pak je er een grotere brok uit.

[ Voor 40% gewijzigd door Contagion op 17-03-2011 14:01 ]


Acties:
  • 0 Henk 'm!

  • MacWolf
  • Registratie: Januari 2004
  • Laatst online: 06-09-2024
Ik vond net deze pagina: http://bartdesmet.net/blo...-Demo-_2B00_-Figures.aspx

Om uiteindelijk de prestaties te verbeteren wordt gebruik gemaakt van een BufferedStream object. Wellicht kan je dat ook proberen.

C#:
1
2
3
4
5
TcpClient clnt = new TcpClient("localhost", 1234);
NetworkStream ns = clnt.GetStream();
BufferedStream bs = new BufferedStream(ns);
for (...; ...; ...)
   bs.WriteByte(...);


Als ik je code goed heb gelezen heb je de tragere manier geïmplementeerd door meteen vanuit het NetworkStream object naar een buffer te schrijven. De BufferedStream geeft op de gelinkte pagina een factor 5 versnelling.

Edit: volgens mij is dit feitelijk dezelfde oplossing die de vorige 2 of 3 posters aandragen, alleen op een nette manier. Het BufferedStream object zal waarschijnlijk pas naar een buffer schrijven als het een redelijke hoeveelheid data bevat.

[ Voor 14% gewijzigd door MacWolf op 17-03-2011 14:11 ]

Microsoft Windows: A thirty-two bit extension and graphical shell to a sixteen-bit patch to an eight-bit operating system originally coded for a four-bit microprocessor which was written by a two-bit company that can't stand one bit of competition.

Pagina: 1