[C] BSD Sockets op Mac OS X 10.6

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • CMG
  • Registratie: Februari 2002
  • Laatst online: 10-12-2024
Ik ben pas begonnen met Objective C, Cocoa, etc, maar de richting die ik op wil leunt toch zwaar op netwerk communicatie.

Heb een boek over BSD sockets er bij gepakt en begonnen. Alles lijkt het gewoon goed te doen, maar verbinden dat weigert 'ie.

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
//
//  main.c
//  DayTimeServer
//
//  Created by Nick Kusters on 4/6/11.
//  Copyright 2011 NKCSS. All rights reserved.
//

#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define MAX_BUFFER                  128
#define DAYTIME_SERVER_PORT         13
#define CONNECTION_MAXIMUM_BACKLOG  5

int main (int argc, const char * argv[])
{

    // insert code here...
    printf("Starting DayTime Server.\n");
    
    int server, connection;
    struct sockaddr_in serverAddress;
    char timebuffer[MAX_BUFFER+1];
    time_t currentTime;
    
    // set socket
    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    // Clear memory
    memset(&serverAddress, 0, sizeof(serverAddress));
    // Set listen parameters
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddress.sin_port = htons(DAYTIME_SERVER_PORT);
    // bind to socket
    bind(server, (struct sockaddr *)&serverAddress, sizeof(serverAddress));
    // start listening & accepting connections.
    listen(server, CONNECTION_MAXIMUM_BACKLOG);
    
    while(1)
    {
        connection = accept(server, (struct sockaddr *)NULL, NULL);
        if(connection > 0)
        {
            // Get current time
            currentTime = time(NULL);
            snprintf(timebuffer, MAX_BUFFER, "%s\n", ctime(&currentTime));
            write(connection, timebuffer, strlen(timebuffer));
            close(connection);
        }
    }
    return 0;
}


Als ik dan probeer te verbinden:
Nick-Kusterss-Mac-mini:~ nick$ telnet localhost 13
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying fe80::1...
telnet: connect to address fe80::1: Connection refused
Trying 127.0.0.1...
telnet: connect to address 127.0.0.1: Connection refused
telnet: Unable to connect to remote host
Nick-Kusterss-Mac-mini:~ nick$
Iemand tips/pointers wat ik kan gaan checken of waar ik de fout in ga?

Heb al gezocht of er iets van een firewall in Mac OS X zit maar dat is niet het geval.

NKCSS - Projects - YouTube


Acties:
  • 0 Henk 'm!

Verwijderd

Een goede website met duidelijke uitleg over sockets op UNIX systemen (dus ook Mac OS X) is deze.

Daarnaast, je probeert port 13 te openen, maar dat mag niet als je geen sudo rechten hebt. Probeer het eens met sudo ervoor :).

Dus bijvoorbeeld:

code:
1
sudo ./daytimeserver


Daarmee gaat het wel lukken. Of je veranderd de port naar iets boven de 1024, aangezien alle poorten onder de 1024 gereserveerd zijn (z.g.n. well-known ports).

Als je bijvoorbeeld 1300 kiest, denk ik niet dat je nog tegen problemen aan loopt :).

C:
1
#define DAYTIME_SERVER_PORT 1300


edit:
Overigens, dat had je met wat debuggen ook kunnen vinden, aangezien bind() dan een error zou returnen (iets anders dan 0 dus) ;).

[ Voor 54% gewijzigd door Verwijderd op 06-04-2011 18:55 ]


Acties:
  • 0 Henk 'm!

  • CMG
  • Registratie: Februari 2002
  • Laatst online: 10-12-2024
Verwijderd schreef op woensdag 06 april 2011 @ 18:49:
Een goede website met duidelijke uitleg over sockets op UNIX systemen (dus ook Mac OS X) is deze.

Daarnaast, je probeert port 13 te openen, maar dat mag niet als je geen sudo rechten hebt. Probeer het eens met sudo ervoor :).

Dus bijvoorbeeld:

code:
1
sudo ./daytimeserver


Daarmee gaat het wel lukken. Of je veranderd de port naar iets boven de 1024, aangezien alle poorten onder de 1024 gereserveerd zijn (z.g.n. well-known ports).

Als je bijvoorbeeld 1300 kiest, denk ik niet dat je nog tegen problemen aan loopt :).

C:
1
#define DAYTIME_SERVER_PORT 1300


edit:
Overigens, dat had je met wat debuggen ook kunnen vinden, aangezien bind() dan een error zou returnen (iets anders dan 0 dus) ;).
Sudo is leuk als je een command wilt uitvoeren in bash, maar ik ben hier C aan het programmeren :) bij bind & accept komt geen sudo kijken en voor zover ik weet heeft telnet geen sudo nodig om zijn werk te doen. Heb het wel even geprobeerd, daar niet van, maar maakt dus geen verschil.

Bedankt voor de referentie, maar die verteld niet veel anders dan mijn boek (BSD Socket Programming from a Multi-Language Perspective).
http://beej.us/guide/bgne...glepage/bgnet.html#accept

NKCSS - Projects - YouTube


Acties:
  • 0 Henk 'm!

  • CMG
  • Registratie: Februari 2002
  • Laatst online: 10-12-2024
Excuses; bind geeft wel degelijk -1 terug :(

maar eens zoeken hoe ik ga fixen dat ik vanuit Xcode dit wel kan gaan debuggen.

[ Voor 91% gewijzigd door CMG op 06-04-2011 19:03 ]

NKCSS - Projects - YouTube


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 20-09 18:51
CMG schreef op woensdag 06 april 2011 @ 18:59:
Sudo is leuk als je een command wilt uitvoeren in bash, maar ik ben hier C aan het programmeren :) bij bind & accept komt geen sudo kijken en voor zover ik weet heeft telnet geen sudo nodig om zijn werk te doen.
Dan weet je het verkeerd. ;) Akathos heeft namelijk gelijk: een gewone gebruiker kan geen poorten onder de 1024 binden. Het gaat dan dus om de server, niet de client (telnet in dit geval).
CMG schreef op woensdag 06 april 2011 @ 19:00:
bind geeft geen error, bind werkt.
Hoe weet je dat? Je checkt de returnvalues van die socketfuncties niet eens!

Je programma is een stuk robuuster als je van alle system calls die kunnen falen (en dat kunnen ze bijna allemaal) de returnvalues checkt, en als die een fout aangeven (meestal door -1 te retourneren) errno te inspecteren (of te printen met perror() bijvoorbeeld). Dan kun je zien welke system calls falen, en waarom.

Acties:
  • 0 Henk 'm!

  • CMG
  • Registratie: Februari 2002
  • Laatst online: 10-12-2024
Soultaker schreef op woensdag 06 april 2011 @ 19:06:
[...]

Dan weet je het verkeerd. ;) Akathos heeft namelijk gelijk: een gewone gebruiker kan geen poorten onder de 1024 binden. Het gaat dan dus om de server, niet de client (telnet in dit geval).

[...]

Hoe weet je dat? Je checkt de returnvalues van die socketfuncties niet eens!

Je programma is een stuk robuuster als je van alle system calls die kunnen falen (en dat kunnen ze bijna allemaal) de returnvalues checkt, en als die een fout aangeven (meestal door -1 te retourneren) errno te inspecteren (of te printen met perror() bijvoorbeeld). Dan kun je zien welke system calls falen, en waarom.
Had mijn bericht al aangepast, nogmaals sorry.

Het probleem was dat zowel mijn boek, als de getoonde referentie in voorbeelden nergens rekening houd met een bind failure. Omdat ik niet wist dat dit standaard vanuit Xcode niet zou werken, leverde dat de verwarring op. Ben dus ook blij dat ik nu weet waar 't hem in zit & waar ik verder kan zoeken.

Heb zelf ook de code maar aangepast zodat 't wat duidelijke wordt.

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
//
//  main.c
//  DayTimeServer
//
//  Created by Nick Kusters on 4/6/11.
//  Copyright 2011 NKCSS. All rights reserved.
//

#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define MAX_BUFFER                  128
#define DAYTIME_SERVER_PORT         13
#define CONNECTION_MAXIMUM_BACKLOG  5

int main (int argc, const char * argv[])
{

    // insert code here...
    printf("Starting DayTime Server.\n");
    
    int server, connection;
    struct sockaddr_in serverAddress;
    char timebuffer[MAX_BUFFER+1];
    time_t currentTime;
    
    // set socket
    server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    // alloc memory
    memset(&serverAddress, 0, sizeof(serverAddress));
    // Set listen parameters
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddress.sin_port = htons(DAYTIME_SERVER_PORT);
    
    // bind to socket
    if(bind(server, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) == 0)
    {
        // Bind success
        printf("Socket has been bound to port %i\n", DAYTIME_SERVER_PORT);
        // start listening & accepting connections.
        if(listen(server, CONNECTION_MAXIMUM_BACKLOG) == 0)
        {
            while(1)
            {
                connection = accept(server, (struct sockaddr *)NULL, NULL);
                if(connection > 0)
                {
                    // Get current time
                    currentTime = time(NULL);
                    snprintf(timebuffer, MAX_BUFFER, "%s\n", ctime(&currentTime));
                    write(connection, timebuffer, strlen(timebuffer));
                    close(connection);
                }
            }
        }
        else
        {
            printf("Listen failed.\n");
        }
    }
    else
    {
        printf("Failed to bind to port %i", DAYTIME_SERVER_PORT);
    }
    return 0;
}

NKCSS - Projects - YouTube


Acties:
  • 0 Henk 'm!

Verwijderd

Daarnaast, als je Xcode gebruikt, build die gewoon een binary in je project folder. Daar zit een folder 'build/debug' in (waarschijnlijk) waarin de build staat. Als je die vanuit de Terminal uitvoert, lukt het prima :).

Acties:
  • 0 Henk 'm!

  • DexterDee
  • Registratie: November 2004
  • Laatst online: 19-09 16:54

DexterDee

I doubt, therefore I might be

MacBook:~ DexterDee$ sudo ./test
Starting DayTime Server.
Socket has been bound to port 13

MacBook:~ DexterDee$ telnet localhost 13
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying fe80::1...
telnet: connect to address fe80::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Wed Apr  6 19:17:13 2011

Zoals Akathos al aangaf, met sudo lukt het prima om op een poortje onder 1024 te binden :)

Klik hier om mij een DM te sturen • 3245 WP op ZW


Acties:
  • 0 Henk 'm!

  • CMG
  • Registratie: Februari 2002
  • Laatst online: 10-12-2024
Verwijderd schreef op woensdag 06 april 2011 @ 19:19:
Daarnaast, als je Xcode gebruikt, build die gewoon een binary in je project folder. Daar zit een folder 'build/debug' in (waarschijnlijk) waarin de build staat. Als je die vanuit de Terminal uitvoert, lukt het prima :).
Ik kom van een .NET achtergrond, ben gewoon gewend om vanuit de IDE te runnen & debuggen totdat hij klaar voor release is :)

Weer wat bijgeleerd.

Xcode starten via SUDO kan, maar dan kan je weer niet bij je lokale GIT repositories.

Enige manier om het 'netjes' te doen vanuit Xcode is door de root user te enablen en remote debugging via SSH op te zetten, daar voel ik me nog niet zo happy bij atm, dus dat komt later nog wel een keer.

[ Voor 0% gewijzigd door CMG op 06-04-2011 19:24 . Reden: typo: totday => totdat ]

NKCSS - Projects - YouTube


Acties:
  • 0 Henk 'm!

Verwijderd

Of gewoon een port boven de 1023 kiezen :+
Pagina: 1