Toon posts:

[C++]Sockets probleem

Pagina: 1
Acties:

Verwijderd

Topicstarter
Hallo allen,

ik moest voor school een opdracht maken waarbij een client en een server voorkwamen. Een vereiste hierbij was dat de client en de server beide in een andere taal werden geschreven. Op zich werkt de handel nu prima, de client is in java geschreven, en de server in C++. Er is echter één probleempje (althans, dat vindt de leraar :p) De server voert geen andere taken uit zolang hij luistert voor connecties. Hieronder staat de oorspronkelijke code, zoals deze van msdn is gehaald. Bij deze code treedt hetzelfde probleem op.

code:
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
void main() {
  //----------------------
  // Initialize Winsock.
  WSADATA wsaData;
  int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
  if (iResult != NO_ERROR)
    printf("Error at WSAStartup()\n");

  //----------------------
  // Create a SOCKET for listening for
  // incoming connection requests.
  SOCKET ListenSocket;
  ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (ListenSocket == INVALID_SOCKET) {
    printf("Error at socket(): %ld\n", WSAGetLastError());
    WSACleanup();
    return;
  }

  //----------------------
  // The sockaddr_in structure specifies the address family,
  // IP address, and port for the socket that is being bound.
  sockaddr_in service;
  service.sin_family = AF_INET;
  service.sin_addr.s_addr = inet_addr("127.0.0.1");
  service.sin_port = htons(27015);

  if (bind( ListenSocket, 
    (SOCKADDR*) &service, 
    sizeof(service)) == SOCKET_ERROR) {
    printf("bind() failed.\n");
    closesocket(ListenSocket);
    return;
  }

  //----------------------
  // Listen for incoming connection requests.
  // on the created socket
  if (listen( ListenSocket, 1 ) == SOCKET_ERROR)
    printf("Error listening on socket.\n");

  //----------------------
  // Create a SOCKET for accepting incoming requests.
  SOCKET AcceptSocket;
  printf("Waiting for client to connect...\n");

  //----------------------
  // Accept the connection.
  while(1) {
    AcceptSocket = SOCKET_ERROR;
    while( AcceptSocket == SOCKET_ERROR ) {
      AcceptSocket = accept( ListenSocket, NULL, NULL );
    }
    printf("Client connected.\n");
    ListenSocket = AcceptSocket;
    break;
  }

  // afhandelen connectie...
}


Het probleem hierbij is, dat als de server voor connecties wacht, het programma blijft 'hangen', de repaintfunctie wordt oa niet meer uitgevoerd. Om het programma af te sluiten, verzendt de client een speciale code, zodat de server ophoudt met luisteren voor connecties. Ik heb het getest, en hij hangt in de accept(). Is er een eenvoudige manier om dit elegant op te lossen, zonder dat ik de hele server op de kop moet gooien? :'( Ik heb wat gelezen over non blocking e.d., maar dat lijkt mij aardig ingewikkeld, en bovendien werkt dit opzich, afgezien dat hij niet repaint enzo :9

[ Voor 3% gewijzigd door Verwijderd op 07-06-2006 23:10 ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 22-01 23:51

NMe

Quia Ego Sic Dico.

C++:
1
2
3
 while( AcceptSocket == SOCKET_ERROR ) {
   AcceptSocket = accept( ListenSocket, NULL, NULL );
}
Maak daar eens een if van, zodat ie ook doorgaat als er niets doorkomt. Je kan je code toch gewoon door laten gaan, en bij de volgende iteratie van de main loop kijken of er misschien wat door je socket komt?

edit:
Waarom post iedereen de laatste tijd toch code tussen [small] tags? We hebben [code]-tags hoor.

Overigens is hier geen C++ aan, ik zie alleen maar native C-code?

[ Voor 23% gewijzigd door NMe op 07-06-2006 23:15 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Verwijderd

Topicstarter
ik heb het dan in code tags gezet, ik zag ze niet staan bij het aanmaken van het topic :)


een if ipv een while maakt geen verschil, dan blijft hij alsnog hangen. Als ik deze regel toevoeg in de code, voor de listen() aanroep

code:
1
WSAAsyncSelect (ListenSocket,Handle,1111,0);


dan blijft hij niet hangen, alleen ik heb geen idee hoe ik dan een nieuwe connectie afvang 8)7


Overigens is hier geen C++ aan, ik zie alleen maar native C-code?


Dit is ongeveer de code die ik gebruik in mijn programma, de foutmeldingen print ik uit naar een memoveld e.d., maar verder is het gelijk.

[ Voor 25% gewijzigd door Verwijderd op 07-06-2006 23:20 ]


  • GX
  • Registratie: Augustus 2000
  • Laatst online: 14-05-2025

GX

Nee.

Als je je socket in non-blocking zet schiet hij er langs wanneer er neits te doen is tot de volgende keer dat hij daar langs komt.

Met GNU C++ los ik het in ieder geval met `select' op:
DESCRIPTION
The functions select() and pselect() wait for a number of file descrip-
tors to change status.
Misschien dat er net zoiets is voor Windows.

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 21:20
GX schreef op woensdag 07 juni 2006 @ 23:30:
Misschien dat er net zoiets is voor Windows.
select wel iig

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik denk dat op windows WSAAsyncSelect en WSAEventSelect te prefereren zijn boven select(), tenzij je echt portable code wil schrijven.
Verwijderd schreef op woensdag 07 juni 2006 @ 23:13:
een if ipv een while maakt geen verschil, dan blijft hij alsnog hangen. Als ik deze regel toevoeg in de code, voor de listen() aanroep

code:
1
WSAAsyncSelect (ListenSocket,Handle,1111,0);
Weet je wel wat WSAAsyncSelect doet? Lijkt me niet anders zat je nu niet met je handen in het haar ;). Lees de documentatie van die functie eens.

WSAAsyncSelect zorgt ervoor dat er een message naar je window wordt gestuurd bij bepaalde events, zodat je die in je message handler van je window kunt afhandelen. Je kunt zelf je message id kiezen (gebruik daarvoor de WM_USER...0x7fff range) en voor welke events je een message krijgt. Jij geeft momenteel 0 mee zodat je nooit een message zal ontvangen, maar de socket wel non-blocking wordt gemaakt (nu ik hier zo over schrijf besef ik me ineens dat dat ook de reden is dat je 'm überhaupt aanroept - je hebt immers ook helemaal geen window).

En je wilt juist toch dat hij dan niet blijft hangen? WSAAccept geeft dan INVALID_SOCKET terug en een WSAEWOULDBLOCK error code (die je kunt opvragen met WSAGetLastError()). Als dat het geval is weet je dus dat er nog geen nieuwe socket is en kun je tussentijds andere dingen doen.

Een andere optie is wellicht werken met threads.

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.


Verwijderd

Topicstarter
Bedankt voor de reacties :) Momenteel zit ik op stage, dus ik kan het niet uitproberen, maar als ik straks thuiskom zal ik er mee aan de slag gaan!

Hoe zit het eigenlijk met threads in C++, zou dat een kleine wijziging zijn, of moet de programmacode daar totaal voor over de kop worden gegooid?

  • Invisible_man
  • Registratie: Juni 2006
  • Laatst online: 11:27
Threads kunnen aardig wat koppijn veroorzaken aangezien je dan bijvoorbeeld functies van je gui niet direct meer kan aanspreken (dat Async verhaal komt dan oa naar voren). Ikzelf heb het in C++ ooit eens opgelost door aan de hand van een timer (bijvoorbeeld) 10 x per seconde te kijken of er data beschikbaar is en die dan te verwerken.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 18:45

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op donderdag 08 juni 2006 @ 11:49:
Hoe zit het eigenlijk met threads in C++, zou dat een kleine wijziging zijn, of moet de programmacode daar totaal voor over de kop worden gegooid?
Zie de _beginthread en _endthread functies :)
Invisible_man schreef op donderdag 08 juni 2006 @ 11:55:
Threads kunnen aardig wat koppijn veroorzaken aangezien je dan bijvoorbeeld functies van je gui niet direct meer kan aanspreken (dat Async verhaal komt dan oa naar voren). Ikzelf heb het in C++ ooit eens opgelost door aan de hand van een timer (bijvoorbeeld) 10 x per seconde te kijken of er data beschikbaar is en die dan te verwerken.
Ten eerste heeft hij geen GUI, ten tweede is het handig om je GUI code dan ook niet op te splitsen over meerdere threads, maar juist je socket handling in een andere thread te doen. :) Maar je hebt gelijk dat je idd voorzichtig moet zijn met synchroniseren en alle problemen die daarbij komen 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.


  • Invisible_man
  • Registratie: Juni 2006
  • Laatst online: 11:27
Ten eerste heeft hij geen GUI, ten tweede is het handig om je GUI code dan ook niet op te splitsen over meerdere threads
Heb je helemaal gelijk in :), ik haalde het eigenlijks meer aan als voorbeeld waarbij je deze "kopzorgen" vaak vind, vooral als je nog maar net met threads begint en je van te voren niet altijd weet waar je rekening mee moet halen.
Pagina: 1