PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [Waste.Pro] Content Grabber



solanum
29.03.2003, 13:14
Hallo, ich bastle im Moment ein wenig an einem Programm, welches die letzten Themen des Waste-Productions.Com Boards ausliest. Voraussetzung ist die Datei www.waste-productions.com/community/grabbing.php, welche vom Prinzip schon fertig ist. Sie wird vom Code zwar später noch verbessert, bleibt aber äußerlich gleich. Diese XML Datei soll dann vom Grabber ausgelesen und interpretiert werden. Evtl. könnte man das Programm, welches hier entstehen soll auch als Framework verwenden und später eine GUI herum bauen, jedoch habe ich davon keine Ahnung.
Da meine C Kenntnisse sehr zu wünschen übrig lassen, könnt ihr ja evtl. einmal über den Code drüberlesen. Im Moment empfängt er nur den Inhalt der grabbing.php, doch selbst das klappt schon nicht: Er empfängt zwar, stürzt aber danach ab. Hier also der Code.
#include <stdio.h>
#include <windows.h>
#include <winsock.h>

long StartWinsock(void) {
WSADATA wsa;
return WSAStartup(MAKEWORD(2, 0), &wsa);
}

int GetAddress(char* host, SOCKADDR_IN* addr) {
unsigned long address;
HOSTENT* he;

if(host == NULL || addr == NULL) {
return SOCKET_ERROR;
}

address = inet_addr(host);
if(address != INADDR_NONE) {
addr->sin_addr.s_addr = address;
return 0;
}
else {
he = gethostbyname(host);
if(he == NULL) {
return SOCKET_ERROR;
}
else {
memcpy(&(addr->sin_addr), he->h_addr_list[0], 4);
return 0;
}
}
}

int main() {
long rc = StartWinsock();
SOCKET s;
SOCKADDR_IN addr;
char buffer[512];

if(rc != 0) {
printf("Error: Winsock");
return 1;
}

s = socket(AF_INET, SOCK_STREAM, 0);
if(s == INVALID_SOCKET) {
printf("Error: Socket");
return 2;
}

memset(&addr, 0, sizeof(SOCKADDR_IN));

addr.sin_family = AF_INET;
addr.sin_port = htons(80);

rc = GetAddress("www.waste-productions.com", &addr);
if(rc == SOCKET_ERROR) {
printf("Error: Address");
return 3;
}

rc = connect(s, (SOCKADDR*)&addr, sizeof(SOCKADDR));
if(rc == SOCKET_ERROR) {
printf("Error: Connect");
return 4;
}

strcpy(buffer, "GET /community/grabbing.php HTTP/1.1\r\nHost: www.waste-productions.com\r\n\r\n");
rc = send(s, buffer, strlen(buffer), 0);

while(rc = recv(s, buffer, sizeof(buffer) - 1, 0)) {
if(rc != 0) {
buffer[rc] = 0;
}

if(rc == SOCKET_ERROR) {
continue;
}

printf("%s", buffer);
}

closesocket(s);
WSACleanup();

return 0;
}Die eigentliche Aufgabe wird es später sein, die XML Datei zu parsen. Ich hatte eigentlich nicht vor, einen bestehenden Parser zu verwenden. Habt ihr evtl. jetzt schon Ideen, warum er am Ende abstürzt?

solanum

theclaw
30.03.2003, 14:11
Hi.

ich hab gerade keine Gelgenheit das zu testen. :)
Aber ich denke der fehler ist in:



memcpy(&(addr->sin_addr), he->h_addr_list[0], 4);


Also ich denke du kopierst da den Inhalt von h_addr_list[0] in &sin_addr.. sprich du hast nachher in sin_addr als Adresse die eigentlichen Werte.

(Bin mir überhaupt nicht sicher.)

AFAIK wär's so richtig:



memcpy(addr->sin_addr, he->h_addr_list[0], 4);


Sorry wenn's dann immer noch nicht geht :)

Bye.
theclaw

solanum
30.03.2003, 20:09
Hallo, erst einmal: Schön zu hören, dass es überhaupt jemanden interessiert :)

Nun aber zu Deinem Vorschlag: Ich habe von Socketprogrammierung wenig Ahnung, aber da er den Inhalt schon holt, sollte die Sache mit der Auflösung der Domain nicht das Problem sein. Mein Debugger sagt mir, dass das Problem in der Zeile
while(rc = recv(s, buffer, sizeof(buffer) - 1, 0)) { liegt. Ich kann jedoch nicht sagen warum.
Sollte dieses Problem behoben sein, könnte man sich an das Parsen der XML Datei machen, wobei man er überlegen sollte, ob das Programm ein Backend für eine GUI sein soll. Wie sieht es mit Interesse eurerseits aus?

solanum

dumm'
30.03.2003, 20:40
Interessieren tut mich das Projekt auch, wo es doch das gleiche, inzwischen Jahre alte Prinzip verfolgt, wie es fuer das JBB Tray geplant war. Nur bin ich immernoch im JBB Tray und hab zur Zeit andere Sachen. CurveBall halt. ;)

Aber trotzdem ein paar Tips:
* schreibt den HTTP Client nicht selbst.
* solltet ihr wirklich keinen zur Verfuegung stehenden Parser benutzen und euch an den anpassen, seid euch darueber i klaren, dass dies mit der groesste Aufwand im projekt wird. Besonders, wenn ihr auf C setzt.
* wenn ihr den Parser selbst schreiben wollt, haltet euch an keinen std., der mehr verlangt, als ihr braucht. Nicht gebrauchte Dinge kosten Zeit ... und Zeit ist das, was am Ende immer fehlt.
* Macht euch genaue Gedanken ueber Zielgruppe, Kapazitaeten und legt die Software entsprechend aus. Mit wenigen Versuchen haben wir damals beim Tray zehntausende Zugriffe in kurzer Zeit erzeugt.
* ein Team suchen, dass moeglichst alle geplanten Aufgabenbereiche abdeckt. Schwer zu finden. Ich weiss wovon ich rede. :/
* die Software und alle Schnittstellen allg. auslegen. Darin liegt der Erfolg von einer solchen Software.
* auch Dinge denken, die man erst garnicht beachtet. Bspweise, wie man Threads abonnieren soll als Benutzer
* ...

Konzept -> Programmierung -> Umsetzung ;)

solanum
30.03.2003, 21:26
etuli, ich denke, wir haben andere Vorstellungen vom Content Grabber. Ich sehe darin eigentlich mehr den Sinn des Lernens. Wenn es nichts wird - Schade, aber kein Weltuntergang. Trotzdem werde ich mit expat mal einen XML Parser ansehen. Dass, wenn ich ihn nicht nehme, kein echter XML Parser rauskommen wird, ist klar. Er soll dann einfach nur seinen Sinn erfüllen.

Zum Code: Hm, der Fehler lag wohl bei meinem C++ Compiler, welcher mit C Code nicht zurecht kam. Der Code ansich funktioniert wunderbar.

solanum

solanum
31.03.2003, 18:45
Ein Kumpel und ich haben uns mittlerweile soweit abgesprochen, dass wir doch eher Deinen Vorstellungen entgegenkommen werden, etuli. Folgende Änderungen wurden besprochen: Curl zum handlen des HTTP Verkehrs expat oder einen ähnlichen XML zum parsen Aufgesetzt auf ein Linuxsystem (evtl. später portieren)

solanum
01.04.2003, 21:35
#include <stdio.h>
#include <curl/curl.h>
#include <expat.h>

struct memory{
char *content;
int size;
};

static void elementstart(void *userData, const char *name, const char **atts) {
if(!strcmp("thread", name)) {
printf("%s\n", name);
}
}

static void elementend(void *userData, const char *name) {
//printf("ende");
}

int parse_data(void *ptr, int size, int nmemb, void *data) {
register int realsize = size * nmemb;
struct memory *mem = (struct memory *)data;
mem->content = (char *)realloc(mem->content, mem->size + realsize + 1);

if (mem->content) {
memcpy(&(mem->content[mem->size]), ptr, realsize);
mem->size += realsize;
mem->content[mem->size] = 0;
}

return realsize;
}

int main(void) {
char *xmlfile = "www.waste-productions.com/community/grabbing.php";
struct memory xml;

xml.content = NULL;
xml.size = 0;

CURL *curl;
CURLcode res;
XML_Parser p;

curl = curl_easy_init();

if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, xmlfile);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(curl, CURLOPT_MUTE, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, parse_data);
curl_easy_setopt(curl, CURLOPT_FILE, (void *)&xml);

curl_easy_perform(curl);
curl_easy_cleanup(curl);

p = XML_ParserCreate(NULL);
XML_SetElementHandler(p, elementstart, elementend);
do{
XML_Parse(p, xml.content, xml.size, 0);
}while(!feof((FILE*)xml.content));

XML_ParserFree(p);
//printf("%s", xml.content);
}

return 0;
}Nun ja, wir sind nun mittlerweile soweit, dass die XML Datei heruntergeladen wird. Dies geschieht mit Hilfe der libcurl. Der Content wird dann mittels expat interpretiert. Jedoch wird im Moment nur der Name des Tags (also Beispielsweise "Thread") und nicht der Inhalt (also Beispielsweise "Was tut ihr bei Langeweile?"). Na ja, mal suchen, was wie wir da nun dran kommen.

;)

solanum

nimrod
02.04.2003, 13:30
sers
evtl. hilft das n bissel bei expat:
http://www.xml.com/pub/a/1999/09/expat/index.html
http://www.xml.com/search/index.ncsp?sp-q=expat

bho

solanum
02.04.2003, 16:03
nimrod, Dein erster Link war Gold wert. Der momentane Status ist, dass es ein Programm gibt, welches die Datei holt, parst und Titel sowie Topicname ausgibt. Das eigentliche Ziel ist eigentlich erreicht. Trotzdem wird es weiter gehen mit dem Grabber. Wie es genau aussehen wird, weiß jedoch noch niemand, aber es bilden sich einige Ideen heraus. Im Anhand findet ihr eine tar.gz mit Executable sowieso Source. Viel Vergnügen.

solanum

http://www.waste-productions.com/community/attachments/grabber.tar.gz

solanum
10.04.2003, 21:40
2 Neuigkeiten:

1. Hm, die folgende Schleife macht ein paar Probleme:
do{
XML_Parse(p, xml.content, xml.size, 0);
}while(!feof((FILE*)xml.content));Linux kommt damit wohl zurecht, aber unter Windows friert der ganze Rechner ein xD Hm, weiss jemand Rat?

2. Das ganze wird später wohl in die Systray gesteckt. Ein Icon wird dort mittlerweile schon einmal angezeigt.

solanum

solanum
11.04.2003, 08:24
Problem wurde einfach so gelöst:int len = strlen(xml.content) - 1;
int i = 0;

while(i < len) {
XML_Parse(p, xml.content, xml.size, 0);
i++;
}

solanum
11.04.2003, 19:03
So, es gibt erfreuliche Neuigkeiten: Unter Windows werden die Daten gegrabbed und geparsed. Das ganze wurde mit MessageBoxen testweise probiert und es funktioniert wunderbar. Die MessageBoxen sind natürlich wieder ausgebaut.
Im SysTray (unten rechts in der Taskbar neben der Uhr) wird ein kleines Icon angezeigt. Sonst sieht man nichts vom Grabber. Dieses Icon soll sich ändern, wenn neue Beiträge auf dem Board geschrieben wurden - dies funcktioniert jedoch noch nicht.
Rechtsklick auf das Icon bewirkt, dass der Grabber geschlossen wird.
Ein Linksklick bewirkt, dass das Board im Standardbrowser aufgerufen wird.Im Moment macht der Grabber noch Probleme, wenn man nicht mit dem Internet verbunden ist, aber das sollte eigentlich recht einfach zu fixen sein. Code und EXE gibt es später.

solanum