Διάβασμα απο το αρχείο dedomena.html

Συζητήσεις για την γλώσσα C και C++

Συντονιστές: WebDev Moderators, Super-Moderators

Απάντηση
master3763
Δημοσιεύσεις: 65
Εγγραφή: 12 Δεκ 2008 16:10
Επικοινωνία:

Διάβασμα απο το αρχείο dedomena.html

Δημοσίευση από master3763 » 29 Αύγ 2009 20:52

Γεια σε όλους ! θα ήθελα να ρωτήσω , πως μπορώ να διαβάσω δεδομένα αλλά και να τα εμφανίσω στο πρόγραμμα μου, από μία ιστοσελίδα ;
Μάλλον θα υπάρχει κάποιο script στη C++ που να το κάνει αυτό.

www.freewebs.com/mypage/dedomaena.html

Με λίγα λόγια θέλω να διαβάσω δεδομένα από την το αρχείο dedomena.html που βρίσκετε σε κάποιον απομακρυσμένο server (freewebs.com) .
Το διάβασμα από ένα αρχείο txt μου είναι γνωστό .
Πώς όμως θα διαβάσω τα δεδομένα που βρίσκονται σε αρχείο .html σε ένα server ;

Άβαταρ μέλους
soteres2002
S. & H. Moderator
Δημοσιεύσεις: 1524
Εγγραφή: 05 Μαρ 2004 22:17
Τοποθεσία: Ιωάννινα

Διάβασμα απο το αρχείο dedomena.html

Δημοσίευση από soteres2002 » 29 Αύγ 2009 23:04

Αυτό που ζητάς αφορά το πως θα επικοινωνήσεις με έναν απομακρυσμένο διακομιστή ΗΤΤΡ για να πάρεις ένα έγγραφο. Αυτό γίνεται με 2 διαφορετικούς τρόπους (αλλά ουσιαστικά είναι το ίδιο):
α) χρησιμοποιείς BSD sockets σε Linux/Unix ή Winsock σε Windows, κάνεις connect() στην ΙΡ του σερβερ και στέλνεις μια αίτηση GET για να πάρεις το έγγραφο. Η ανάγνωση γίνεται με κλήσεις συστήματος read()/write().
β) χρησιμοποιείς κάποιο abstraction layer πχ την βιβλιοθήκη w3c-www ή LWP ( http://www.w3c.org )

Για τη δεύτερη λύση, μπες στο w3c.org και κατέβασε την σχετική βιβλιοθήκη που περιλαμβάνει και παραδείγματα για το πως να την χρησιμοποιήσεις.
Όσον αφορά την πρώτη λύση, δες ένα δικό μου παράδειγμα κώδικα που κάνει αυτό που ζητάς... (Βέβαια, κάνει κάτι παραπάνω από αυτό που ζητάς, χρησιμοποιεί νήματα για να κάνει ταυτόχρονες αιτήσεις για το ίδιο έγγραφο, αλλά never mind!)

Κώδικας: Επιλογή όλων

//// client.c ////
/**
 * Sotiris Karavarsamis. (C) All rights reserved. 2008.
 */

#ifndef _REENTRANT
  #define _REENTRANT
#endif

#include <stdio.h>
#include <errno.h>

/* Headerfiles for Unix/Linux */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <getopt.h>
#include <unistd.h>
#include <fcntl.h>

#define closesocket&#40;s&#41; close&#40;s&#41;

#ifndef MAXHOSTNAMELEN
  #define MAXHOSTNAMELEN 128
#endif

/* http used to be requested on port 80 */
#define HTTPD_PORT 4001

struct sockaddr_in server;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
long int throughput = 0;
int port = HTTPD_PORT;
int concurrency = 5;
int joined = 0;
int outfile = -2;
char *resource = "";
char *hostname = "";

void usage&#40;char *bin&#41; &#123;
    fprintf&#40;stderr, "Usage&#58; %s &#91;-p portnum&#93; &#91;-h&#93; \n",bin&#41;;
    fprintf&#40;stderr, "-p portnumber &#58; alternate port number.\n"&#41;;
    fprintf&#40;stderr, "-t target hostname to lookup\n"&#41;;
    fprintf&#40;stderr, "-c concurrency&#58; set concurrency level &#40;default 5&#41;\n"&#41;;
    fprintf&#40;stderr, "-r resource&#58; string which represents the resource to requestn\n"&#41;;
    fprintf&#40;stderr, "-o output&#58; write received input to a file instead of stdout\n"&#41;;
    fprintf&#40;stderr, "-s HTTP hostname field value&#58; default is empty\n"&#41;;
    fprintf&#40;stderr, "-h &#58; print usage.\n"&#41;;
    exit&#40;1&#41;;
&#125;

void *retrieve&#40;void *arg&#41; &#123;
    int fd;
    int count = 0;
    char buffer&#91;4096&#93;;
    
    fd = &#40;int *&#41;arg;
    pthread_mutex_lock&#40;&lock&#41;;
    if&#40;connect&#40;fd, &#40;struct sockaddr*&#41;&server, sizeof&#40;server&#41;&#41; < 0&#41; &#123;
	pthread_mutex_unlock&#40;&lock&#41;; 
        perror&#40; "can't connect to server"&#41;;
        return&#40;NULL&#41;;
    &#125;
    pthread_mutex_unlock&#40;&lock&#41;;

    /* create and send the http GET request */
    sprintf&#40;buffer, "GET /%s HTTP/1.0\r\nHost&#58; %s\r\nAccept-Encoding&#58;\r\n\r\n", resource, hostname&#41;;
    send&#40;fd, buffer, strlen&#40; buffer&#41;, 0&#41;;

    /* get the answer from server and put it out to stdout */
    do &#123;
       count = recv&#40;fd, buffer, sizeof&#40;buffer&#41;, 0&#41;;
       
       if&#40;outfile != -2&#41;
        write&#40;outfile, buffer, count&#41;;
       else
         write&#40;1, buffer, count&#41;;
       
       pthread_mutex_lock&#40;&lock&#41;;
        throughput += count;
       pthread_mutex_unlock&#40;&lock&#41;;
    &#125; while &#40;count > 0&#41;;
    
    /* close the connection to the server */
    closesocket&#40;fd&#41;;
    pthread_exit&#40;"thread terminated"&#41;;
&#125;

void ext&#40;int sig&#41; &#123;
        printf&#40;"\n"&#41;;
	if&#40;joined < concurrency&#41; &#123;
		printf&#40;"Punt! Not all threads &#40;%d&#41; have joined yet...\n", joined&#41;;
	&#125;
	
	printf&#40;"%lu bytes have been transfered.\n", throughput&#41;;
	exit&#40;EXIT_SUCCESS&#41;;
&#125;

int main&#40; int argc, char **argv&#41;
&#123;
    struct hostent *host_info;
    unsigned long addr;
    int *sock;
    int c, i, ret;
    pthread_t *tid;
    char *target = NULL;
    
    while&#40;&#40;c = getopt&#40;argc,argv,"c&#58;t&#58;p&#58;hr&#58;o&#58;s&#58;"&#41;&#41; != -1&#41; &#123;
        switch&#40;c&#41; &#123;
	  case 'c'&#58;
	    concurrency = atoi&#40;optarg&#41;;
	    break;
          case 'p'&#58;
            port = atoi&#40;optarg&#41;;
            break;
          case 't'&#58;
	    target = strdup&#40;&#40;char *&#41;optarg&#41;;
            break;
          case 'h'&#58;
            usage&#40;argv&#91;0&#93;&#41;;
	    exit&#40;0&#41;;
            break;
          case 'r'&#58;
            resource = strdup&#40;&#40;char *&#41;optarg&#41;;
            break;
          case 'o'&#58;
            outfile = open&#40;&#40;char *&#41;optarg, O_RDWR | O_CREAT | O_TRUNC, 0655&#41;;
            if&#40;outfile == -1&#41; &#123;
              perror&#40;"open"&#41;;
              exit&#40;1&#41;;
            &#125;
          case 's'&#58;
            hostname = strdup&#40;&#40;char *&#41;optarg&#41;;
            break;
        &#125;
    &#125;

    signal&#40;SIGINT, ext&#41;;
    
    if&#40;!target || concurrency <= 0&#41; &#123;
	usage&#40;argv&#91;0&#93;&#41;;
        exit&#40;EXIT_FAILURE&#41;;
    &#125;

    sock = &#40;int *&#41;malloc&#40;concurrency*sizeof&#40;int&#41;&#41;;
    if&#40;sock == NULL&#41; &#123;
      perror&#40;"malloc&#40;&#41;"&#41;;
    &#125;
    
    tid = &#40;pthread_t *&#41;malloc&#40;concurrency * sizeof&#40;pthread_t&#41;&#41;;
    if&#40;tid == NULL&#41; &#123;
      perror&#40;"malloc&#40;&#41;"&#41;;
    &#125;

    fprintf&#40;stdout, "&#91;*&#93; turing concurrency to %d\n", concurrency&#41;;

    /* create socket */
    for&#40;i = 0; i < concurrency; i++&#41; &#123;
	    sock&#91;i&#93; = socket&#40;AF_INET, SOCK_STREAM, 0&#41;;
	    if &#40;sock&#91;i&#93; < 0&#41; &#123;
	        perror&#40;"socket&#40;&#41;"&#41;;	
        	exit&#40;1&#41;;
    	    &#125;
    &#125;
    
    memset&#40; &server, 0, sizeof &#40;server&#41;&#41;;
    host_info = gethostbyname&#40;target&#41;;
    if &#40;NULL == host_info&#41; &#123;
        fprintf&#40; stderr, "could not resolve host '%s'!\n", target&#41;;
        exit&#40;1&#41;;
    &#125;

    memcpy&#40; &#40;char *&#41;&server.sin_addr, host_info->h_addr, host_info->h_length&#41;;
    server.sin_family = AF_INET;
    server.sin_port = htons&#40;port&#41;;
    
    for&#40;i = 0; i < concurrency; i++&#41; &#123;
      ret = pthread_create&#40;&tid&#91;i&#93;, NULL, retrieve, &#40;void *&#41;sock&#91;i&#93;&#41;;
      if&#40;ret != 0&#41; &#123;
          fprintf&#40;stderr, "Could not spawn thread %d\n", i + 1&#41;;
          exit&#40;EXIT_FAILURE&#41;;
      &#125;
    &#125;
    
    for&#40;i = 0; i < concurrency; i++&#41; &#123;
       ret = pthread_join&#40;tid&#91;i&#93;, NULL&#41;;
       if&#40;ret != 0&#41; &#123;
          perror&#40;"pthread_join&#40;&#41;"&#41;;
       &#125;
       joined++;
    &#125;
 
    if&#40;concurrency == joined&#41; &#123;
      printf&#40;"All threads have terminated normally!\n"&#41;;
    &#125;
    printf&#40;"Totally transfered %ld bytes from %d concurrent connections...\n", throughput, concurrency&#41;;

    if&#40;sock&#41;
      free&#40;sock&#41;;
    
    if&#40;tid&#41;
      free&#40;tid&#41;;
    
    if&#40;outfile != -2&#41;
      close&#40;outfile&#41;;

    exit&#40;EXIT_SUCCESS&#41;;
&#125;
Μελέτησε τον κώδικα, και ό,τι απορίες έχεις εδώ είμαστε! Επίσης, για ευκολία σου προτείνω να μην δώσεις σημασία στις συναρτήσεις pthread_*: δώσε κυρίως βάση στην συνάρτηση retrieve() που κάνει την μεταφορά του εγγράφου.

Αυτό που πρέπει να κατανοήσεις για τα sockets είναι η ακολουθία hostname resolution -> socket() -> connect() -> read/write() .

Ο κώδικας αυτός δουλεύει μόνο σε Unix (αλλά φαντάζομαι με Ming/GW κάνεις άνετα εκτελέσιμο για windows), και μπορείς να το κάνεις compile με την εντολή:

Κώδικας: Επιλογή όλων

gcc client.c -o client -lpthread
Δυστυχώς, δεν έχω κάτι πιο απλό να σου δείξω... είχα στο blog μου έναν πιο απλό κώδικα που έκανε GET ΗΤΤΡ μεταφορά, αλλά είναι down και δεν έχω κάποιο local copy να σου στείλω... Φυσικά κάνοντας λίγο Googling μπορείς να βρεις κάποιο παράδειγμα που να κάνει ακριβώς αυτό που ζητάς, έψαξα λίγο μήπως βρω κάποια σελίδα αλλά μπα..

Σου δίνω και ένα λινκ από το δυνατό μάθημα "Προγραμματισμός Δικτύων" από το τμήμα Πληροφορικής του Πανεπιστημίου Ιωαννίνων που περιέχει πληροφορίες για clients, servers, πρωτόκολλα επικοινωνίας κτλ που όλα γενικά είναι σχετικά με αυτά που ρωτάς, αν θες να ψάξεις το κατιτίς παραπάνω στο θέμα αυτό...
URL: http://www.cs.uoi.gr/~ntarmos/Courses/N ... ogramming/

master3763
Δημοσιεύσεις: 65
Εγγραφή: 12 Δεκ 2008 16:10
Επικοινωνία:

Διάβασμα απο το αρχείο dedomena.html

Δημοσίευση από master3763 » 30 Αύγ 2009 17:21

Τόσο σύνθετο είναι το ζήτημα δηλαδή ?
Μήπως υπάρχει τίποτα έτυμο ρε παιδιά ? Η τίποτα απλό ?
Θα προσπαθήσω να το τρέξω τον κώδικα αλλά μάλλον θα χρειαστώ πολύ χρόνο......... :-)

Άβαταρ μέλους
soteres2002
S. & H. Moderator
Δημοσιεύσεις: 1524
Εγγραφή: 05 Μαρ 2004 22:17
Τοποθεσία: Ιωάννινα

Διάβασμα απο το αρχείο dedomena.html

Δημοσίευση από soteres2002 » 31 Αύγ 2009 01:49

master3763 έγραψε:Τόσο σύνθετο είναι το ζήτημα δηλαδή ?
Μήπως υπάρχει τίποτα έτυμο ρε παιδιά ? Η τίποτα απλό ?
Από τι στιγμή που πρέπει να διαβάσεις δεδομένα από το δίκτυο (κάτι που δεν έχει σχέση με είσοδο/έξοδο σε αρχεία στο δίσκο), πρέπει να χρησιμοποιήσεις υποδοχές (sockets). Απο κει και πέρα, μπορείς να χρησιμοποιήσεις βιβλιοθήκες που αφαιρούν όλη την πολυπλοκότητα του προβλήματος και εσύ απλά κάνεις μερικές κλήσεις συναρτήσεων της βιβλιοθήκης... Δυστυχώς είναι μονόδρομος και δεν υπάρχει άλλος τρόπος...

master3763
Δημοσιεύσεις: 65
Εγγραφή: 12 Δεκ 2008 16:10
Επικοινωνία:

Διάβασμα απο το αρχείο dedomena.html

Δημοσίευση από master3763 » 14 Ιούλ 2010 21:35

Αυτο ειναι ενα προγραμμα για Linux . Αυπαρχει τυποτα για windows ?

Άβαταρ μέλους
dva_dev
Script Master
Δημοσιεύσεις: 3790
Εγγραφή: 16 Σεπ 2005 01:32
Επικοινωνία:

Διάβασμα απο το αρχείο dedomena.html

Δημοσίευση από dva_dev » 14 Ιούλ 2010 22:46

Κάνε μια αναζήτηση για InternetOpenUrl ή InternetReadFile και θα βρείς πολύ πράμα. Υπάρχουν αρκετά ολοκληρωμένα παραδείγματα στο codeproject.com και το codeguru.com

Απάντηση

Επιστροφή στο “C, C++”

Μέλη σε σύνδεση

Μέλη σε αυτήν τη Δ. Συζήτηση: Δεν υπάρχουν εγγεγραμμένα μέλη και 0 επισκέπτες