Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

Probleem met sockets

Pagina: 1
Acties:

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
hallo allemaal,

ik wil graag leren hoe je een een networkprogramma maakt en ben daarom als leer project bezig met het maken van een chat programma in c++. Ik heb een paar tutorials gelezen en vervolgens een client en een server geschreven met hele basic functionaliteit. Nu wil ik echter de client en server mergen in 1 programma waarbij de gebruiker kiest of ie wil hosten of wil joinen. Voor het hosten heb ik de volgende functie:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void HostPeer()
{
    while(1)
    {
        //constantly look if there is an incoming connection
        if(networksocket = accept(networksocket,(SOCKADDR*)&addr,&addrlen)) //if there is then accept it
        {
            cout << "Incoming connection!" << endl;
            send(networksocket,&nickname[0],64,NULL); //send own name to connecting client
            recv(networksocket,&peername[0],64,NULL);//receive the name of the connecting client
            cout << "connected with: " << peername << endl;
            return; //return out of the function
        }
    }
}

Het rare is nu alleen dat dit in de server only programma gewoon werkt, dit is een bijna exacte kopie ervan ( en de rest van het progamma is op dezelfde manier opgezet) maar nu werkt het niet.
Als deze functie wordt aangeroepen na het initialiseren van de sockets in instelen van nickname en port dan zie ik altijd staan dat er een netwerkconnectie is, ook als ik geen joinende heb gestart. met andere woorden, de if statement is altijd waar.
Het rare is alleen dat in mijn server programma dezelfde code wordt gebruikt (alleen dan direct in de main en niet een functie) en dan doet ie het wel |:( . Mijn vraag is dus of iemand ziet wat er hier fout gaat want ik snap er helemaal niks meer van omdat ik dezelfde code hergebruik. zelfs de manier waarop de sockets worden ingesteld zijn hetzelfde. alvast bedankt!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
williewonka03 schreef op dinsdag 25 juni 2013 @ 17:38:
Mijn vraag is dus of iemand ziet wat er hier fout gaat
Je zegt zelf al:
williewonka03 schreef op dinsdag 25 juni 2013 @ 17:38:
met andere woorden, de if statement is altijd waar.
Begin daar eens :?
Debuggen: Hoe doe ik dat?

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
ja ik heb dus gebugged en hij zegt gewoon dat die ifstatement waar is, als ik bij de andere code met line for line step doe dan blijft ie gewoon netjes hangen in die loop. wat wel raar is is dat het gele pijltje van de debugging dan verdwijnt ook al zeg ik dat ie gewoon naar de volgende regel moet

  • _js_
  • Registratie: Oktober 2002
  • Laatst online: 25-10 14:28
En wat is dan de volgende stap? Als het if-statement wel waar is maar er blijkbaar toch geen verbinding is... Is er stiekem toch een verbinding? Of klopt het if-statement niet? Of zijn de waarden van de variabelen en de returnvalues niet de waarden die je verwacht? Dat hoort ook allemaal bij debuggen.

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
_js_ schreef op dinsdag 25 juni 2013 @ 18:51:
En wat is dan de volgende stap? Als het if-statement wel waar is maar er blijkbaar toch geen verbinding is... Is er stiekem toch een verbinding? Of klopt het if-statement niet? Of zijn de waarden van de variabelen en de returnvalues niet de waarden die je verwacht? Dat hoort ook allemaal bij debuggen.
het probleem is dat als ik de volgende stap wil zien in de werkende programma dan verdwijnt het stap icoontje en kan ik niet meer stappen, heel raar. in de niet werkende dan gaat ie gewoon de cout statements af. voor de variablen krijg ik een adres voor die socket en dat is dus vreem omdat er geen verbinding wordt gevraagd.
nee er is stiekem niet een verbinding wat als ik alleen de server start van de de werkende dan wacht ie wel gewoon netjes op verbinding. das dus het rare.

  • ThomasG
  • Registratie: Juni 2006
  • Laatst online: 18:54
Je overschrijft je networksocket variabel. Het hevat eerst de descriptor van socket, en daarna de descriptor van accept aanneemt, maar als die van socket wilt gebruiken bij de volgende iteratie. Dat kan nooit de bedoeling zijn.

[ Voor 51% gewijzigd door ThomasG op 25-06-2013 19:03 ]


  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
ThomasG schreef op dinsdag 25 juni 2013 @ 19:00:
Je overschrijft je networksocket variabel. Het hevat eerst de descriptor van socket, en daarna de descriptor van accept aanneemt, maar als die van socket wilt gebruiken bij de volgende iteratie. Dat kan nooit de bedoeling zijn.
ja ik heb ook al keertje met andere naam gedaan maar dan doet ie het nog steeds.
Hmm ik zit nu te denken dat toen ik naam veranderde ik misschien niet geintialiseerd heb. zal dat eens proberen

[ Voor 11% gewijzigd door williewonka03 op 25-06-2013 19:34 ]


  • deadinspace
  • Registratie: Juni 2001
  • Nu online

deadinspace

The what goes where now?

williewonka03 schreef op dinsdag 25 juni 2013 @ 19:33:
Hmm ik zit nu te denken dat toen ik naam veranderde ik misschien niet geintialiseerd heb. zal dat eens proberen
Misschien probeert accept() je dat ook wel te vertellen ;)

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
deadinspace schreef op dinsdag 25 juni 2013 @ 19:46:
[...]

Misschien probeert accept() je dat ook wel te vertellen ;)
Dat is een van de eerste dingen die je je af moet vragen inderdaad. Je if controleert de return waarde van "accept". Als dat blijkbaar altijd true oplevert, ga je eerst kijken wat accept terug geeft: MSDN: accept function (Windows)

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
Woy schreef op dinsdag 25 juni 2013 @ 19:50:
[...]

Dat is een van de eerste dingen die je je af moet vragen inderdaad. Je if controleert de return waarde van "accept". Als dat blijkbaar altijd true oplevert, ga je eerst kijken wat accept terug geeft: MSDN: accept function (Windows)
ja dat had ik idd opgezocht maar het geeft een address terug en ik weet niet precies hoe ik dat adres controleer. maar ik weet mss wat het probleem is zoals 2 posts terug staat. ik ga dat nu ff proberen.

EDIT: nope dat werkt ook niet, ik heb nu een tweede socket gemaakt en dan die in de ifstatement gezet en het werkt nog steeds niet:
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
void InitSockets() //sets up the socket
{
    networksocket           = socket(AF_INET,SOCK_STREAM,NULL);
    peersocket              = socket(AF_INET,SOCK_STREAM,NULL);
    addr.sin_addr.s_addr    = inet_addr(IP_peer.c_str());
    addr.sin_port           = htons(port);
    addr.sin_family         = AF_INET;
}


void HostPeer()
{
    while(1)
    {
        //constantly look if there is an incoming connection
        if(peersocket = accept(networksocket,(SOCKADDR*)&addr,&addrlen)) //if there is then accept it
        {
            cout << "Incoming connection!" << endl;
            send(peersocket,&nickname[0],64,NULL); //send own name to connecting client
            recv(peersocket,&peername[0],64,NULL);//receive the name of the connecting client
            cout << "connected with: " << peername << endl;
            return; //return out of the function
        }
    }
}

Ik krijg nog steeds dat ie meteen zegt dat ie een verbinding heeft. ik snap er echt niks van want het is nu letterlijk hetzelfde als de andere en die werkt wel

EDIT2: ok ik heb gekeken of er een errorcode is met WSAGetLastError() en die returned 10022 want correspondeert met WSAEINVAL wat volgens msdn betekend:
code:
1
2
3
Invalid argument.

    Some invalid argument was supplied (for example, specifying an invalid level to the setsockopt function). In some instances, it also refers to the current state of the socket&#8212;for instance, calling accept on a socket that is not listening.

Maar waarom returned ie dan true, in de andere programma die wel werkt passeert ie die ifstatement niet dus dan returned ie niet true. ik zal daar ook ff een WSAGetLastError() call doen.

EDIT3: ok das raar, als ik zo'n call probeer te doen in het andere programma dan blijft ie hangen in de connect functie, net zolang totdat ie een verbinding krijg. waarom krijg ik dat gedrag niet voor de andere, ik geef dezelfde inputargumenten

[ Voor 64% gewijzigd door williewonka03 op 25-06-2013 20:20 ]


  • ThomasG
  • Registratie: Juni 2006
  • Laatst online: 18:54
Ik weet niet of dit al je code is, maar zo ja, dan ben je in ieder geval bind en listen op je server socket vergeten.

  • williewonka03
  • Registratie: Augustus 2010
  • Laatst online: 16-06-2024
ThomasG schreef op dinsdag 25 juni 2013 @ 20:25:
Ik weet niet of dit al je code is, maar zo ja, dan ben je in ieder geval bind en listen op je server socket vergeten.
haha nee dit is niet alle code, das beetje overdreven om te posten toch? kan ik wel doen hoor, maar bind en listen zijn idd de eerste dingen die ik gechecked heb of ik die had

EDIT: ow als ik die call aanroep direct na listen dan geeft ie al een 10022. volgens hier betekend dat er een fout in bound zit. kortom accept wijst naar listen, listen naar bound. ik ga maar eens met die errorfunctie de functies een voor een af kijken waar dat uitkomt

EDIT2: ok bind geeft het volgende:
code:
1
2
3
4
5
6
7
WSAEADDRNOTAVAIL

    

The requested address is not valid in its context.

This error is returned if the specified address pointed to by the name parameter is not a valid local IP address on this computer.


maar ik dacht dat je geen ip hoeft op te geven voor luisteren. dat heb ik dacht ik bij de andere ook niet gedaan. gat ik dat ff checken.

EDIT3: das grappig je moet blijkbaar wel een standaard ip opgeven voor luisteren. dat heb ik bij de andere niet gedaan, maar dat was een c implementatie en ik heb nu wat dingen omgezet naar c++ wat niet uit zou moeten maken. in ieder geval hij skipt de if statement niet meer, probleem is nu dat ie goed joined dus dat ga ik ff op dezelfde manier proberen te achterhalen

EDIT4: das vreemd ik krijg nu een connection refused error als ik wil joinen.

[ Voor 75% gewijzigd door williewonka03 op 25-06-2013 21:29 ]


  • Matis
  • Registratie: Januari 2007
  • Laatst online: 20:57

Matis

Rubber Rocket

Waarom een return icm een while(1) als de accept al blocking is?
De volgorde voor een server socket is grofweg, socket bind listen accept

2 uit 4 zie ik in jouw (gestripte) code niet staan. Ikzelf heb legio server sockets onder Linux opgezet, veelal volgens deze uitgeklede voorbeeldcode
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
/* A simple server in the internet domain using TCP
   The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
     int sockfd, newsockfd, portno;
     socklen_t clilen;
     char buffer[256];
     struct sockaddr_in serv_addr, cli_addr;
     int n;
     if (argc < 2) {
         fprintf(stderr,"ERROR, no port provided\n");
         exit(1);
     }
     sockfd = socket(AF_INET, SOCK_STREAM, 0);
     if (sockfd < 0) 
        error("ERROR opening socket");
     bzero((char *) &serv_addr, sizeof(serv_addr));
     portno = atoi(argv[1]);
     serv_addr.sin_family = AF_INET;
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(portno);
     if (bind(sockfd, (struct sockaddr *) &serv_addr,
              sizeof(serv_addr)) < 0) 
              error("ERROR on binding");
     listen(sockfd,5);
     clilen = sizeof(cli_addr);
     newsockfd = accept(sockfd, 
                 (struct sockaddr *) &cli_addr, 
                 &clilen);
     if (newsockfd < 0) 
          error("ERROR on accept");
     bzero(buffer,256);
     n = read(newsockfd,buffer,255);
     if (n < 0) error("ERROR reading from socket");
     printf("Here is the message: %s\n",buffer);
     n = write(newsockfd,"I got your message",18);
     if (n < 0) error("ERROR writing to socket");
     close(newsockfd);
     close(sockfd);
     return 0; 
}

If money talks then I'm a mime
If time is money then I'm out of time


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
williewonka03 schreef op dinsdag 25 juni 2013 @ 19:51:
[...]

ja dat had ik idd opgezocht maar het geeft een address terug en ik weet niet precies hoe ik dat adres controleer. maar ik weet mss wat het probleem is zoals 2 posts terug staat. ik ga dat nu ff proberen.
Dan moet je wel even verder lezen dan je neus lang is natuurlijk
If no error occurs, accept returns a value of type SOCKET that is a descriptor for the new socket. This returned value is a handle for the socket on which the actual connection is made.


Otherwise, a value of INVALID_SOCKET is returned, and a specific error code can be retrieved by calling WSAGetLastError.
En even doorzoeken levert op
C++:
1
#define INVALID_SOCKET  (SOCKET)(~0)

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • ed800
  • Registratie: Februari 2009
  • Laatst online: 18-11 18:27
williewonka03 schreef op dinsdag 25 juni 2013 @ 19:51:
[...]

ja dat had ik idd opgezocht maar het geeft een address terug en ik weet niet precies hoe ik dat adres controleer. maar ik weet mss wat het probleem is zoals 2 posts terug staat. ik ga dat nu ff proberen.

EDIT: nope dat werkt ook niet, ik heb nu een tweede socket gemaakt en dan die in de ifstatement gezet en het werkt nog steeds niet:
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
void InitSockets() //sets up the socket
{
    networksocket           = socket(AF_INET,SOCK_STREAM,NULL);
    peersocket              = socket(AF_INET,SOCK_STREAM,NULL);
    addr.sin_addr.s_addr    = inet_addr(IP_peer.c_str());
    addr.sin_port           = htons(port);
    addr.sin_family         = AF_INET;
}


void HostPeer()
{
    while(1)
    {
        //constantly look if there is an incoming connection
        if(peersocket = accept(networksocket,(SOCKADDR*)&addr,&addrlen)) //if there is then accept it
        {
            cout << "Incoming connection!" << endl;
            send(peersocket,&nickname[0],64,NULL); //send own name to connecting client
            recv(peersocket,&peername[0],64,NULL);//receive the name of the connecting client
            cout << "connected with: " << peername << endl;
            return; //return out of the function
        }
    }
}

Ik krijg nog steeds dat ie meteen zegt dat ie een verbinding heeft. ik snap er echt niks van want het is nu letterlijk hetzelfde als de andere en die werkt wel

EDIT2: ok ik heb gekeken of er een errorcode is met WSAGetLastError() en die returned 10022 want correspondeert met WSAEINVAL wat volgens msdn betekend:
code:
1
2
3
Invalid argument.

    Some invalid argument was supplied (for example, specifying an invalid level to the setsockopt function). In some instances, it also refers to the current state of the socket&#8212;for instance, calling accept on a socket that is not listening.

Maar waarom returned ie dan true, in de andere programma die wel werkt passeert ie die ifstatement niet dus dan returned ie niet true. ik zal daar ook ff een WSAGetLastError() call doen.

EDIT3: ok das raar, als ik zo'n call probeer te doen in het andere programma dan blijft ie hangen in de connect functie, net zolang totdat ie een verbinding krijg. waarom krijg ik dat gedrag niet voor de andere, ik geef dezelfde inputargumenten
Moet de code op regel 16 overigens net peersocket == accept zijn en niet peer socket = accept?

  • deadinspace
  • Registratie: Juni 2001
  • Nu online

deadinspace

The what goes where now?

williewonka03 schreef op dinsdag 25 juni 2013 @ 19:51:
ja dat had ik idd opgezocht maar het geeft een address terug en ik weet niet precies hoe ik dat adres controleer.
Dat staat in de documentatie (zoals Woy die linkt bijvoorbeeld):
Otherwise, a value of INVALID_SOCKET is returned, and a specific error code can be retrieved by calling WSAGetLastError.
EDIT2: ok ik heb gekeken of er een errorcode is met WSAGetLastError() en die returned 10022 want correspondeert met WSAEINVAL...
Let op dat je alleen WSAGetLastError() mag controleren als accept() INVALID_SOCKET returned! Anders controleer je op de laatste fout die optrad, mogelijk in een andere functie.
Maar waarom returned ie dan true...
Hij returned geen true, hij returned INVALID_SOCKET, wat blijkbaar niet 0 is en dus in een if() evalueert naar true ;)
EDIT3: ok das raar, als ik zo'n call probeer te doen in het andere programma dan blijft ie hangen in de connect functie, net zolang totdat ie een verbinding krijg.
En dat staat ook weer gewoon in de documentatie:
The accept function can block the caller until a connection is present if no pending connections are present on the queue, and the socket is marked as blocking.
waarom krijg ik dat gedrag niet voor de andere, ik geef dezelfde inputargumenten
Nou, blijkbaar niet ;)

De moraal van het verhaal is:
  • Lees de documentatie
  • Controleer de return-values op foutcondities zodat je uitvindt waar het fout gaat en vaak ook (deels) waarom
  • Gebruik debugging om de werkelijke oorzaak te achterhalen
Dan spoor je dit soort fouten snel op.

offtopic:
Ik ben alleen bekend met de POSIX network socket API, en ik blader een beetje door die winsock API heen... Het is gewoon functie voor functie, statuscode voor statuscode de POSIX API maar dan met subtiel andere namen hier en daar... Origineel, Microsoft! Had dan gewoon POSIX geimplementeerd. Maarja, dat was weer te interopabel met andere OSsen geweest zeker :+
ed800 schreef op dinsdag 25 juni 2013 @ 22:40:
Moet de code op regel 16 overigens net peersocket == accept zijn en niet peer socket = accept?
Nee, want hij wil de return value van accept() terecht toewijzen aan peersocket. Een vergelijking zou weinig nut hebben (zeker aangezien peersocket waarschijnlijk uninitialized is).

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 13:12
Matis schreef op dinsdag 25 juni 2013 @ 21:45:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/* A simple server in the internet domain using TCP
   The port number is passed as an argument */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

int main(int argc, char *argv[])
{
...
     portno = atoi(argv[1]);
...
}
Ik las p*rn* :D

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.

Pagina: 1