Toon posts:

[c++] Tegelijk informatie verzenden en ontvangen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Nadat ik wat heb gelezen en geexpirimenteerd met sockets in c++, wou ik een simpele chat progje maken. Console-based. Wat ik nu in mn hoofd heb, je voert de ip van degene in met wie je wil praten, je voert een poort in(standaard 1337 :+ )Degene aan de andere kant doet dat ook en je hebt dan verbinding. Tot zover zal het me wel lukken denk ik.

Maar nu komt het, om tekstberichten te versturen gebruik ik send() en om die te ontvangen gebruik recv(). Nu is het probleem, hoe kan ik allebei de funties naast elkaar draaien. Als alternatief had ik in mn hoofd, dat hij een oneindige loop uitvoert, dus hij controleert of je al iets ontvangen hebt, zo ja drukt ie dat af, en gaat ie naar send(), als je hij binnen x seconden geen invoer heeft, gaat ie weer terug naar het begin van de loop.
Dit is niet echt handig, ik wil hebben dat hij onafhankelijk of ik iets aan het typen ben berichten kunnen ontvangen, en andersom natuurlijk. :P. K ben na wat lezen en googlen erachter gekomen dat ik dan threads moet gebruiken, ik heb hier echter helemaal geen ervaring mee.
Ik heb op google ook gezocht naar tutorials of threading, maar heb echt niets gevonden, alleen wat over threading in linux. Nu is mijn vraag, moet het per se met threading, of is er een andere alternatief?
Zo ja, wat is die alternatief
Zo nee, heeft iemand een goeie link over threading

Alvast bedankt _/-\o_

[edit]
Ik heb dus windows draaien, geen linux. En geeft svp niet alleen maar termen, maar ook een beetje uileg, ben nl behoorlijk n00b

[ Voor 5% gewijzigd door Verwijderd op 29-07-2003 12:47 ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

• Threads (zoek naar pthreads onder Linux)
• Non-blocking sockets

Professionele website nodig?


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Welk OS?
bovendien hoeft het niet per se met threading, alleen dan zul je je eigen toets-afhandeling moeten doen ipv gebruik te maken van bijvoorbeeld istream::readline ()

Als je platform win32 is dan moet je eens in de MSDN naar _beginthread () en _endthread () kijken

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • SPee
  • Registratie: Oktober 2001
  • Laatst online: 15:50
Kun je niet iets met select() ? :?
Daar kun je meerdere read sockets opgeven, meerdere write sockets en een time-out.
Ik weet alleen niet of het alleen voor linux geldt of ook voor windows?

Ik heb voor een netwerk vak gebruik gemaakt van de tutorial van Beej. Dat levert wel veel informatie op.

let the past be the past.


  • bille
  • Registratie: Mei 2000
  • Laatst online: 05-08 23:45

bille

Don't call me Buff

dit zijn best basics... voor je recv() functie zou je een aparte thread kunnen gebruiken.
Om de send() functie uit te voeren kan je idd gebruik maken van keylisteners zodat je zelfs iedere letter direct over je datastream heen kan gooien, of je maakt het iets algemener door bijv. alleen bij de "enter" te laten senden. iig raadt ik je aan met 2 threads te werken, want die recv() functie zal een blocking/polling functie zijn en je wilt naast het pollen van je inkomende verkeer ook wel ffies wat andere dingen regelen, zoals de layout van je GUI goed houden e.d.

Ultra Pilammo 6666Mhz AMD, 4251Mbit/s RAM, Gefors V6666 MegaTurbo, 43" TFS, Ultra 80Gig Firewire netwerkkaart en 5D geluid met 66 speakers in 5 dimensies


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Threads zijn vet overkill voor dit 'probleem'. Beste is gewoon non-blocking sockets te gebruiken, afhankelijk van het platform met select() of onder Win32 overlapped I/O met event objects en WaitForMultipleObjects.

Professionele website nodig?


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Asynchronous I/O is waarschinlijk het mooiste model; dat combineert de simpelheid van single-threaded programma's met de CPU-efficiency van MT

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Ik heb dus windows draaien, geen linux. En geeft svp niet alleen maar termen, maar ook een beetje uileg, ben nl behoorlijk n00b
Als je de goede termen echter in Google steekt krijg je vanzelf de goede algemene uitleg en blijft het vanzelf beter hangen dan dat we je voorkauwen hoe je dit specifieke probleem oplost :)

Professionele website nodig?


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Kijk ook eens naar chapter 5 van m'n winsock tutorial. Die chapter heeft een overzicht van alle I/O models die je met winsock kunt gebruiken, met korte uitleg en voordelen/nadelen. De tutorials is nog lang niet zo ver dat er ook al uitgelegd wordt hoe je alles kan programmeren maar in ieder geval heb je dan een idee van de mogelijkheden..

www.madwizard.org


Verwijderd

Topicstarter
madwizard schreef op 29 July 2003 @ 13:35:
Kijk ook eens naar chapter 5 van m'n winsock tutorial. Die chapter heeft een overzicht van alle I/O models die je met winsock kunt gebruiken, met korte uitleg en voordelen/nadelen. De tutorials is nog lang niet zo ver dat er ook al uitgelegd wordt hoe je alles kan programmeren maar in ieder geval heb je dan een idee van de mogelijkheden..
Thnx, lijkt me een aardige tut. Ik ga m doornemen.

@curry684
Je hebt gelijk :), thnx ik kan weer verder :*)

Verwijderd

Topicstarter
ik ben een simpele chat client aan het maken, maar nu heb ik een probleem. ik heb 2 threads, de main voor het ontvangen en een server_send() voor het versturen, die als het goed is prallel aan elkaar draaien. Maar dat is het probleem niet, in main heb ik de volgende code.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    for( ; ; )
    {
        nBytes= recv(Chat_Server, (char*)&MessageSize, sizeof(MessageSize), 0);

        if (nBytes==SOCKET_ERROR)
        {
            cout<<"Ontvangen van bericht mislukt";
        }
        MessageSize=ntohl(MessageSize);
    
        nBytes=recv(Chat_Client, buffer, MessageSize, 0);
        if(nBytes==SOCKET_ERROR)
        {
            cout<<"Ontvangen van het bericht mislukt!\n";
        }
        buffer[MessageSize]='\0';
    
        printf("Bericht ontvangen: %s\n", buffer);
    }

nu herhaalt ie dit heel snel 8er elkaar. Ik wil eigenlijk hebben dat ie eerst controleert of de socket data bevat. En dan iets in de vorm
if(socket bevat data/is niet leeg)
{
//mn code
}
else
{
sleep(x) ;
continue;
}
dat ie dus controleert of de socket informatie bevat, zoja dan moet ie dat ophalen en afdrukken, zonee moet ie x sec/msec w8en en dan de for loop opnieuw uitvoeren.
Hoe krijg ik dit voor elkaar?
Ik heb na wat lezen begrepen dat dat met select moet, maar nu is mn vraag hoe. Want ik heb van alles geprobeerd, maar het wil maar niet lukken.
http://analyser.oli.tudel...ns/net/html/advanced.html

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Als je blocking sockets gebruikt wacht ie gewoon tot er data is (minimaal 1 byte maar meestal meer).. Bij non-blocking kun je inderdaad select gebruiken. Kijk maar eens bij de documentatie van select, er zijn ook genoeg voorbeelden van.
In je code ga je er trouwens vanuit dat je alle bytes ontvangt die je wilt ontvangen, dat is niet zo.. De eerste recv kan net zo goed 1 byte ontvangen (niet waarschijnlijk maar het kan wel degelijk).. Ga daar dus nooit voor uit..
En wat nog erger is, de buffer lengte voor recv uit de ontvangen data halen is heel erg gevaarlijk. Nu kan de client elke willekeurige grootte opgeven, ook waardes groter dan de echte buffer size. Zo krijg je buffer overflow die uitermate goed te exploiten is...
edit:
Als laatste, ga er ook niet vanuit dat er precies 1 bericht per recv aankomt, het kan ook een half bericht zijn of 2 berichten, TCP behoudt geen message boundaries zoals UDP.

[ Voor 12% gewijzigd door madwizard op 29-07-2003 19:35 ]

www.madwizard.org


Verwijderd

Topicstarter
buffer overflow's vind ik niet zo erg, het is alleen maar voor mezelf, gewoon om te leren werken met sockets enzo. Waar ik aan dacht is om op de client te beperken, zodat je niet meer dan 5000 tekens kan typen.
Wat je bedoelt met dat er per recv maar 1 byte aan kan komen snap ik eik niet 8)7 TCP controleert toch dat alles aankomt. En hoe bedoel je dat er per keer een half bericht kan komen, of dat er 2 berichten kunnen komen.
En als laatste, heb je dan tips hoe het beter kan(ik kan bv niet bedenk hoe ik anders grootte van een bericht moet beperken)

edit:
zou zoiets werken in mijn geval? if((select(1, &Chat_Server, NULL, NULL, &Timeout))==0)
het gaat me om de eerst 2 argumenten van select ;)

[ Voor 17% gewijzigd door Verwijderd op 29-07-2003 20:10 ]


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Verwijderd schreef op 29 July 2003 @ 19:48:
buffer overflow's vind ik niet zo erg, het is alleen maar voor mezelf, gewoon om te leren werken met sockets enzo. Waar ik aan dacht is om op de client te beperken, zodat je niet meer dan 5000 tekens kan typen.
Je kan het beter maar meteen goed leren, want bij serieuze applicaties kunnen zulke dingen grote problemen opleveren. En ookal is dit dan niet zo serieus, het blijft gewoon fout. In een echte situatie heeft het limiteren van de client geen enkele zin als de kwaadaardige user gewoon zelf z'n data stuurt..
Wat je bedoelt met dat er per recv maar 1 byte aan kan komen snap ik eik niet 8)7 TCP controleert toch dat alles aankomt. En hoe bedoel je dat er per keer een half bericht kan komen, of dat er 2 berichten kunnen komen.
In het algemeen: data kan in elke willekeurige verdeling binnenkomen, hoe het dan ook verstuurd is.. Dus als je 4 sends uitvoert met 'aaaa', 'bbbb', 'cccc' en dan 'dddd', kan je alles in 1 recv ontvangen 'aaaabbbbccccdddd', maar ook eerst 'aa' en dan pas de rest, of elke byte apart.. Op zulke kleine schaal zal dat niet gebeuren (houd er evengoed rekening mee) omdat alles toch wel in 1 package gaat, maar op grotere schaal gaat het vaak zo. Stel je stuurt een bericht van 4000 bytes.. Je kan dat dan ontvangen in bijvoorbeeld 4 delen van 1000 bytes (dus 4 recv calls), maar ook bijvoorbeeld eerst 1000 bytes en 2 seconden later de overige 3000 als er opeens iets in het netwerk mis ging ofzo. Op de zelfde manier kunnen 2 berichten van 1000 bytes best als 1 groot blok van 2000 bytes ontvangen worden, of een blok van 1500 en dan van 500, enz enz..
Je zal dus je binnengekomen data moeten bufferen en daar steeds je berichten tussenuit knippen zodra ze volledig binnen zijn..
En als laatste, heb je dan tips hoe het beter kan(ik kan bv niet bedenk hoe ik anders grootte van een bericht moet beperken)
Je houdt altijd een probleem van maximale lengte enzo, maar als je client en server beperkt gaat het in principe goed. Dat neemt niet weg dat je geen maatregelen moet nemen voor als het fout gaat.. Zorg bijvoorbeeld dat als je langere berichten ontvangt, je een foutmelding geeft en de verbinding dichtgooit. Zo houd je attacks buiten de deur maar de gewone gebruiker zal er niks van merken, omdat die een goede client gebruikt die als het goed is nooit te lange berichten stuurt..

www.madwizard.org


Verwijderd

Topicstarter
kun je me misshien toevoegen op msn drhendre@hotmail.com

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 13:19

.oisyn

Moderator Devschuur®

Demotivational Speaker

Over die non-blocking sockets: lees mijn post in het begin van deze thread nog eens. De sockets zijn het probleem niet, maar de invoer van de console wel! Als je namelijk de standaard functies daarvoor gebruikt, zoals bijv. fgets () of std::readline (), dan heb je iets dat blocked totdat er op enter gedrukt wordt. Dat betekent dus dat je alleen berichten kunt ontvangen nadat er op enter is gedrukt, terwijl je juist wil dat dit parallel loopt. Threads is dan een makkelijke oplossing, een andere is een eigen input handler maken zodat je tijdens het wachten op input nog wat anders kunt doen

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1