// Hak|onLine - Randnotizen und Müll...


von Hakon Stand: 23. Juli 2011
So, ich habe mich jetzt lange mit dieser Bibliothek beschäftigt - doch nun bin ich stolz darauf eine erste Version veröffentlichen zu können. Der Name meiner Library ist Jodocus - eine Bibliothek für Windows, geschrieben in C++0x für den Visual Studio 2010 Compiler. Sie unterstützt normale ASCII und Unicode-Codierung, ist exception- und threadsafe und umfasst die Bereiche: Es sind mit Sicherheit noch viele Bugs drin, ich habe mich aber stehts um ein sauberes Interface und die intensive Nutzung von Templates bemüht. Ich bin gerade noch dabei, die Dokumentation fertig zu stellen und werde danach ein paar Beispiele schreiben. Besonders stolz bin ich auf den Netzwerk-Teil meiner Bibliothek - mit ihr kann man elegant äußerst gut skalierende Multithread-Server programmieren. Wer die Bibliothek downloaden will muss hier klicken. Anschließend einfach im Visual Studio 2010 öffnen und kompilieren. Anschließend findet sich als Kompilat eine jodocus.lib, die man zu seinem eigenen Projekt dazulinken muss. Ansonsten einfach die Header einbinden (jodocus.hpp, net/net.hpp etc.). Über ein Feedback würde ich mich sehr freuen!
von Hakon Stand: 3. Februar 2011
Nachdem ich mal wieder kilobyte-weise Spam-Einträge in meinem rudimentären Gästebuch hatte, habe ich jetzt eine genauso rudimentäre "Sicherheitsabfrage" ergänzt. Hoffentlich ist dieser Schutz wirksam und der Bot schlechter programmiert als mein Schutzmechanismus. :)
Aktuell bin ich weiter dabei, einen skalierbaren Windows-Server zu schreiben. Konkret abstrahiere ich den Quellcode etwas (zugegeben wird er boost::asio etwas ähnlich). Momentan ist schon sowas möglich:
Programm zur Ausgabe der IP eines z.B. DNS-Namens #include <iostream>
#include <jodocus/net.hpp>

int main()
try {
typedef jodocus::net::ip::tcp protocol;
jodocus::net::listener listener(jodocus::system().num_cpu);
const protocol::resolver resolver(listener);
std::wstring dns_name; // Adresse eingeben
std::wcout << L"Bitte geben Sie eine URI ein: ";
std::wcin >> dns_name;
std::wcout << L"Bitte warten...\n";
protocol::resolver::const_iterator host;
try {
host = resolver.resolve(dns_name, L"80");
}
catch(const jodocus::net::net_error& e) {
std::wcout << L"Der Name " << dns_name << L" konnte nicht aufgeloest werden!\n"
<< L"Fehlermeldung:\n" << e.what() << L'\n';
std::system("pause");
return 0;
}
std::wcout << L"Die Adressen fuer " << dns_name << L" lauten:\n";
for(; host != protocol::resolver::const_iterator(); ++host)
std::wcout << *host << std::endl;
std::system("pause");
}
catch(const jodocus::net::net_error& e) {
std::cerr << e.what() << '\n';
std::system("pause");
}
catch(const std::exception& e) {
std::cerr << e.what() << '\n';
std::system("pause");
}
Was der Laie vermutlich nicht sieht: meine Library ist komplett IP-versionsunabhängig (was asio zwar auch ist) und benutzt intern einen Socket-Pool, der für den Nutzer unsichtbar ist (das macht asio nicht). Ob und wie viel Performance das bringen kann, werde ich erst in Zukunft herausfinden.
von Hakon Stand: 12. August 2010
So, der Server befindet sich nun kurz vor dem ersten Beta-Release. Ich habe mich entschieden den Server ab Version 0.4 Alpha (in der sich der Server gerade befindet) "Jodocus" zu nennen. Momentan bin ich eher damit beschäftigt ihn in jeder Situation zu testen: 4000 Clients verbinden sich gleichzeitig, es werden X Megabytes gleichzeitig empfangen/gesendet, 200 Clients brechen die Verbindung ab, während Daten gesendet werden etc. Das Ergänzen und Features und das Beheben zahlreicher Bugs aus v0.3 haben den Server mittlerweile um 600 Zeilen größer werden lassen.

Um die Frage zu beantworten, was der Jodocus nun eigentlich macht, so kann ich nur darauf antworten, dass er quasi nichts tut. Er ist ein Echo-Server. Alles, was man ihm schickt, wird byte-genau an den Absender zurückgesendet. Versucht man nun z.B. per Firefox über http://localhost den laufenden Server zu erreichen, so wird einem im Browser am Ende nur der eigene HTTP-Request ausgegeben.
Das mag nicht gerade spektakulär klingen, das spannende an dem Serversystem ist jedoch, dass es auf Multicore-Architektur und somit Multithreads aufbaut. Die Asynchrone Datenübertragung und die Parallelität von CPUs geben dem Server signifikante Geschwindigkeitsvorteile und er ist in der Lage, bei tausenden von gleichzeitigen Verbindungen in gleicher Zeit die Echos zu empfangen und zurück zu senden, er ist also skalierbar (auch wenn zugegeben die Multicore-Architektur von Microsoft durch die Winsock2-API vorgegeben ist.)

Ich werde nach dem Beheben der Bugs in der 0.4-Version eine erste Messdatenreihe anlegen, um echte Werte zu messen und sie in Diagrammen an zu zeigen. Ich bin ziemlich gespannt, was für Ergebnisse zu sehen sein werden, besonders, wie sich der Server bei 1000, 5000, 10000 Verbindungen skaliert.
Bis dahin habe ich hier erst mal den Changelog von Jodocus hochgeladen, von v0.1 bis jetzt. Für die Kenner von Winsock könnte das vielleicht interessant sein.
Changelog von Jodocus
von Hakon Stand: 2. August 2010
Im Zuge der Ferien habe ich mein altes Server-Projekt weitergeschrieben, und bin mittlerweile bei stolzen 1000 Zeilen angekommen. Das Projekt tauft sich auf den Codenamen "HakServ" und befindet sich noch im Alpha-Status (v0.3). Sobald ich die 0.5 überschritten habe werde ich es hier als Beta mal zum Angebot stellen.
von Hakon Stand: 6. März 2010
Tja, momentan nicht viel los. :) Ich kann nur eines tun, und zwar stolz meinen kleinen C++-Taschenrechner mit Parser zu präsentieren. Was er kann? Nun ja, mit der Eingabe von Dezimalzahlen kommt er noch nicht klar, aber zumindest die Grundarithmetik funktioniert. Für die Windowser hier eine kleine exe: Taschenrechner herunterladen Und für alle anderen, die können sich den Code selber kompilieren. :)
Vorsicht, Code: #include <iostream>
#include <fstream>
#include <string>

struct lexer {
enum auxvar {
number, plus = '+', minus = '-', mul = '*', div = '/', err = -1, lp = '(', rp = ')'
};

static auxvar analyse(const char c) {
switch(c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
return number;
case plus: case mul: case div: case minus: case lp: case rp:
return auxvar(c);
default:
return err;
}
}
};

template <typename Ch = char, typename St = std::basic_istream<Ch> >
class parser {
private:
typename lexer::auxvar current;
Ch token;
St& stream;

double next() {
stream.get(token);
if(token == ' ') next();
current = lexer::analyse(token);
return token - '0';
}

double expr() {
double left = term();
for(;;)
switch(current) {
case lexer::plus:
left += term();
break;
case lexer::minus:
left -= term();
break;
case lexer::lp:
{
double res = expr();
if(current != lexer::rp) {
std::cerr << "erwarte ')'!\n";
return lexer::err;
}
left = res;
next();
break;
}
case lexer::number:
left = left * 10 + (token - '0');
next();
break;
default:
return left;
}
}

double term() {
double left = prim();
for(;;)
switch(current) {
case lexer::mul:
left *= prim();
break;
case lexer::div:
if(double d = prim()) {
left /= d;
break;
}
std::cerr << "Keine Division durch 0 moeglich!\n";
return -1;
case lexer::number:
left = left * 10 + (token - '0');
next();
break;
default:
return left;
}
}

double prim() {
double left = next();
switch(current) {
case lexer::number:
left = token - '0';
next();
return left;
case lexer::minus:
left = -prim();
return left;
case lexer::plus:
return prim();
case lexer::lp:
{
double res = expr();
if(current != lexer::rp) {
std::cerr << "erwarte ')'!\n";
return lexer::err;
}
next();
return res;
}
default:
std::cerr << "Falsche Eingabe: '" << token << "', Erwarte Primary\n";
return lexer::err;
}
}

public:
parser(St& is)
: current(lexer::err), stream(is), token(0) {
if(!stream) throw std::runtime_error("parse error: fehlerhafter stream\a\n");
}

double parse() { return expr(); }
};

int main() {
std::cout << "Kontextfreier Arithemtikparser" << std::endl
<< "\tvon Hakon Hirsch" << std::endl
<< std::endl << "Beispiel: 4+(6*7)/((4+7)*2)+8" << std::endl;
parser<> p(std::cin);
for(;;) {
double result = p.parse();
std::cout << result << std::endl;
}
}
Alle die, die damit was anfagen können, fragen vielleicht nach Einrückungen. Ja, ich habe eigentlich welche drin. Aber ich hatte kein Bock noch mehr mit diesem PHP rum zu frickeln. :)
Naja, meine kleine Kommentarkiste ist wohl auf der Liste von Spambots gelandet, dann ergreife ich mal besser "Maßnahmen". Bis dahin bau ich erst mal fleißig weiter an Programmen. Mein nächstes Thema betrifft dann eher Algorithmen und Datenstrukturen (besonders der B+-Baum). Was das ist? Wikipedia hilft...
von Hakon Stand: 6. Dezember 2009
So, 3 Tage sind vergangen, ein erster Kommentar ist erschienen (sehr schön, ich habe scheinbar doch noch regelmäßige Besucher :D ) und ich bin immer noch nicht viel weiter bei meinen Überlegungen. Liegt vermutlich daran, dass ich den Kopf auch gerade mit optimierter Teilmengenkonstruktion und dem hier voll habe:
Vorsicht, Code: template <unsigned order, typename key_t, typename payload_t, typename compare_t, typename allocator_t> const node<order, key_t, payload_t, compare_t, allocator_t>* tree<order, key_t, payload_t, compare_t, allocator_t>::invalid_ptr = reinterpret_cast<const node*>(-1);

Naja, wie auch immer. Zurück zum Thema:
Wenn ich die Seite farbiger mache, würde ich zu einem blauen Design tendieren, dunkelblau mit Schwarz und einem gelegentlichen Weiß-Kontrast. Oder wäre wer mehr für Rot? Ganz ehrlich: ich habe keinen blassen Schimmer. :) Bei meinen ganzen Designs, die ich je gemacht habe, war immer eine Spur "Inspiration" von anderen Websites mit drin. :)
Wie gesagt, ich mag kein Designen. :) (Benutze ich eigentlich zu viele Smileys? ;) )
Deshalb: Bei einer sinnvollen Idee, hier gleich einen Kommentar zu abgeben, oder einfach nur mal, um zu grüßen, denn ich bin schon interessiert, wer sich noch die Zeit nimmt, diese Website zu besuchen, obwohl ich sie seit Monaten nicht gepflegt hatte.

PS: Andere Frage: Was macht man, wenn am Ende eines Teilsatzes innerhalb einer Klammer ein Smiley steht? Sowas: (bla... :)) oder eher (bla... :) ) oder vielleicht sogar (bla... (:)? Ich stehe da jedes mal auf dem Schlauch, wenn ich in so eine Situation komme.
von Hakon Stand: 3. Dezember 2009
Hallo! Ich habe meine Website nun wirklich lange genug auf Eis gelegt. Es wird Zeit, dass ich mal wieder etwas mit ihr anfange, wozu habe ich sonst die Domain gekauft? :)
Bevor ich aber richtig loslege, muss ich mir noch mal ein paar Design-Ideen durch den Kopf gehen lassen (ich mag kein Designen) und mich an meine früheren Lektionen Webprogrammierung erinnern, das ist alles schon etwas eingestaubt. :) Wie auch immer, das ist alles, was zu sehen ist und es wird vermutlich auch erst ein mal alles sein, was ich hier darstellen werde. Ich schreibe hier etwas blogartig den Stand meiner neuen Webseite, es ist also lohnenswert, immer wieder mal vorbei zu schauen. Ich werde mich bemühen, hier alles auf dem aktuellsten Stand zu halten. Die Inhalte werden auf jeden Fall etwas mit Programmieren zu tun haben, vielleicht ein paar Artikel, Quellcodes o.ä.

Wir werden sehen.

Update: Ich habe ein kleines Kommentar-System hinbekommen, fleißiges schreiben gestattet. :)