<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Funktionsweise von IO-Streams]]></title><description><![CDATA[<p>Hallo!<br />
Ich will aus Übungszwecken, um die IO-Streams besser zu verstehen, die Library von C++ um IO-Sockets erweitern. Leider finde ich nie so die rechten Beispiele, die ausführlich genug sind.</p>
<p>Ich habe eine Klasse, basic_sockbuf, die ich einmal von std::basic_streambuf und zum anderen privat von einer Ressourcenklasse ableite:</p>
<pre><code class="language-cpp">template &lt;typename Ch, typename Tr = std::char_traits&lt;Ch&gt; &gt;
	class basic_sockbuf : private stream_resource&lt;Ch&gt;, public std::basic_streambuf&lt;Ch, Tr&gt; {
  // ...
}

// Ressourcenklasse

template &lt;typename Ch&gt;
class stream_resource {
protected:
	Ch* pbuf;

public:
	stream_resource(std::streamsize n = 64) {
		try {
			pbuf = new Ch[n];
		}
		catch(const std::bad_alloc&amp;) {
			throw net_error(&quot;socket buffer too big&quot;);
		}
	}

	~stream_resource() {
		delete [] pbuf;
	}
};
</code></pre>
<p>1. Wie groß soll ich die Puffergröße defaulttechnisch wählen? Ich habe jetzt einfach irgendeine 2er-Potenz genommen (64 * sizeof(Ch)), aber was eignet sich am besten als Default?</p>
<p>2. Wie sollte ein Fehlermanagement aussehen? Speziell die Kommunikation zwischen Stream und Puffer. Funktionsrückgabewerte, also 0 für failure sind ja schön und gut, aber bei sockets kann ja so viel schiefgehen zur Runtime, dass die Info badbit irgendwie nicht sehr viel hilft, wenn z.B. u. Windows winsock.dll nicht geladen werden konnte, man keinen Socket-Deskriptor erstellen kann usw. usf. Ich habe an Exceptions gedacht, das scheint aber mehr als Kommunikationslayer zwischen Applikation und Stream als zwischen Stream und Puffer zu wirken (--&gt; exceptions()). Wie kann ich sinnvolles Debugmanagement anbieten?</p>
<p>3. Wie arbeitet z.B. die Funktion overflow() genau? Sie wird aufgerufen, wenn der pptr() an den eptr() rankommt, aber wo steht das? Muss ich das selber definieren? Stroustrup meint: &quot;Nur die Funktionen, die zur Initialisierung und der Pufferungsstrategie betreffen, [...] müssen überladen werden.&quot; Und was dann? Wird der ganze Puffer entleert, wenn es zum Overflow kommt? Ich muss in ihr ja irgendwann den Systemcall send() aufrufen.</p>
<p>Sorry für den vielen Text, aber ich stehe leider etwas auf dem Schlauch, da ich einfach nichts gescheites im Netz finde (da werden einfach nur die Implementierungen von filebufs benutzt, also nichts allzu fundamentales, aber sockets unterscheiden sich da ja). Ich habe mir auch die Implementierung der Standardlibary angeschaut, aber die ist ziemlich schwer leserlich.<br />
:xmas2:</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/257803/funktionsweise-von-io-streams</link><generator>RSS for Node</generator><lastBuildDate>Wed, 09 Sep 2026 05:43:32 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/257803.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 03 Jan 2010 16:31:24 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Sun, 03 Jan 2010 16:31:24 GMT]]></title><description><![CDATA[<p>Hallo!<br />
Ich will aus Übungszwecken, um die IO-Streams besser zu verstehen, die Library von C++ um IO-Sockets erweitern. Leider finde ich nie so die rechten Beispiele, die ausführlich genug sind.</p>
<p>Ich habe eine Klasse, basic_sockbuf, die ich einmal von std::basic_streambuf und zum anderen privat von einer Ressourcenklasse ableite:</p>
<pre><code class="language-cpp">template &lt;typename Ch, typename Tr = std::char_traits&lt;Ch&gt; &gt;
	class basic_sockbuf : private stream_resource&lt;Ch&gt;, public std::basic_streambuf&lt;Ch, Tr&gt; {
  // ...
}

// Ressourcenklasse

template &lt;typename Ch&gt;
class stream_resource {
protected:
	Ch* pbuf;

public:
	stream_resource(std::streamsize n = 64) {
		try {
			pbuf = new Ch[n];
		}
		catch(const std::bad_alloc&amp;) {
			throw net_error(&quot;socket buffer too big&quot;);
		}
	}

	~stream_resource() {
		delete [] pbuf;
	}
};
</code></pre>
<p>1. Wie groß soll ich die Puffergröße defaulttechnisch wählen? Ich habe jetzt einfach irgendeine 2er-Potenz genommen (64 * sizeof(Ch)), aber was eignet sich am besten als Default?</p>
<p>2. Wie sollte ein Fehlermanagement aussehen? Speziell die Kommunikation zwischen Stream und Puffer. Funktionsrückgabewerte, also 0 für failure sind ja schön und gut, aber bei sockets kann ja so viel schiefgehen zur Runtime, dass die Info badbit irgendwie nicht sehr viel hilft, wenn z.B. u. Windows winsock.dll nicht geladen werden konnte, man keinen Socket-Deskriptor erstellen kann usw. usf. Ich habe an Exceptions gedacht, das scheint aber mehr als Kommunikationslayer zwischen Applikation und Stream als zwischen Stream und Puffer zu wirken (--&gt; exceptions()). Wie kann ich sinnvolles Debugmanagement anbieten?</p>
<p>3. Wie arbeitet z.B. die Funktion overflow() genau? Sie wird aufgerufen, wenn der pptr() an den eptr() rankommt, aber wo steht das? Muss ich das selber definieren? Stroustrup meint: &quot;Nur die Funktionen, die zur Initialisierung und der Pufferungsstrategie betreffen, [...] müssen überladen werden.&quot; Und was dann? Wird der ganze Puffer entleert, wenn es zum Overflow kommt? Ich muss in ihr ja irgendwann den Systemcall send() aufrufen.</p>
<p>Sorry für den vielen Text, aber ich stehe leider etwas auf dem Schlauch, da ich einfach nichts gescheites im Netz finde (da werden einfach nur die Implementierungen von filebufs benutzt, also nichts allzu fundamentales, aber sockets unterscheiden sich da ja). Ich habe mir auch die Implementierung der Standardlibary angeschaut, aber die ist ziemlich schwer leserlich.<br />
:xmas2:</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1831541</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1831541</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Sun, 03 Jan 2010 16:31:24 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Sun, 03 Jan 2010 19:02:30 GMT]]></title><description><![CDATA[<p>Warum leitest du denn die Klasse privat ab?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1831663</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1831663</guid><dc:creator><![CDATA[Vererb0r]]></dc:creator><pubDate>Sun, 03 Jan 2010 19:02:30 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Sun, 03 Jan 2010 19:30:27 GMT]]></title><description><![CDATA[<p>So verhindere ich Schwierigkeiten im Destruktor von basic_streambuf, wenn er auf den physikalischen Puffer zugreifen will. Hier wird erst der streambuf zerstört, danach erst das Array.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1831687</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1831687</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Sun, 03 Jan 2010 19:30:27 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Mon, 04 Jan 2010 19:36:06 GMT]]></title><description><![CDATA[<p>Ad aCTa schrieb:</p>
<blockquote>
<p>1. Wie groß soll ich die Puffergröße defaulttechnisch wählen? Ich habe jetzt einfach irgendeine 2er-Potenz genommen (64 * sizeof(Ch)), aber was eignet sich am besten als Default?</p>
</blockquote>
<p>.. so groß, dass Dein darunter liegendes Device (Sockets) damit zurechtkommt. Am besten Du probierst es einfach aus.</p>
<p>Ad aCTa schrieb:</p>
<blockquote>
<p>2. Wie sollte ein Fehlermanagement aussehen? Speziell die Kommunikation zwischen Stream und Puffer. Funktionsrückgabewerte, also 0 für failure sind ja schön und gut, aber bei sockets kann ja so viel schiefgehen zur Runtime, dass die Info badbit irgendwie nicht sehr viel hilft, wenn z.B. u. Windows winsock.dll nicht geladen werden konnte, man keinen Socket-Deskriptor erstellen kann usw. usf. Ich habe an Exceptions gedacht, das scheint aber mehr als Kommunikationslayer zwischen Applikation und Stream als zwischen Stream und Puffer zu wirken (--&gt; exceptions()).</p>
</blockquote>
<p>Der std::streambuf bietet Dir zwei Arten von Fehlerbehandlung an. Zum einen kannst Du bei einem Aufruf von overflow (bein Schreiben) oder underflow (beim Lesen) jeweils mit traits_type::eof() zurückkommen, d.h. das Schreiben bzw. Lesen war nicht erfolgreich und der überlagerte Stream geht dann in den Fehlerzustand. Oder Du wirfst eine Exception - ohne weitere Kommandos wird dann im Stream die Exception gefangen und das std::ios_base::badbit gesetzt. Das entspricht einem fatalen Fehler, der nur mit Abbruch und wieder aufsetzen der Verbindung zu beheben ist.</p>
<p>Falls Du den spezifischen Fehler weiterleiten möchtest, so musst Du im stream (std::ostream oder std::istream) mit stream.exception(std::ios_base::badbit) das Exception-Flag so setzen, dass eine Exception des streambufs weitergeleitet wird. In den aufrufenden Funktionen kann man dann die exception fangen und die anhängende Meldung z.B. ausgeben.</p>
<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Wie kann ich sinnvolles Debugmanagement anbieten?</p>
</blockquote>
<p>Was verstehst Du darunter? Ich würde Dir eine Art Trace-System (evt. schaltbar empfehlen), was alle ein- und ausgehenden Meldungen mitprotokolliert.</p>
<p>Ad aCTa schrieb:</p>
<blockquote>
<p>3. Wie arbeitet z.B. die Funktion overflow() genau? Sie wird aufgerufen, wenn der pptr() an den eptr() rankommt, aber wo steht das? Muss ich das selber definieren? Stroustrup meint: &quot;Nur die Funktionen, die zur Initialisierung und der Pufferungsstrategie betreffen, [...] müssen überladen werden.&quot; Und was dann? Wird der ganze Puffer entleert, wenn es zum Overflow kommt? Ich muss in ihr ja irgendwann den Systemcall send() aufrufen.</p>
</blockquote>
<p>Es steht im C++-Standard (), aber das ist keine Quelle, um zu lernen, wie es funktioniert, sondern wird Dich nur frustrieren, wenn Du nicht schon weißt, wie man einen streambuf verwendet. Im Grunde gibt es meines Wissens nur eine vernünftige Quelle - das ist das Buch <a href="http://www.amazon.de/Standard-Iostreams-Locales-Programmers-Reference/dp/0321585585/ref=sr_1_11?ie=UTF8&amp;s=books-intl-de&amp;qid=1262632941&amp;sr=8-11" rel="nofollow">'Standard C++ Iostreams and Locales'</a>. Das Überladen eines streambufs wird dort auf vielleicht einem Dutzend Seiten beschrieben. Ansonsten suche in diesem Forum nach <code>streambuf</code> - da wirst Du auch einiges finden - oder frage einfach konkret nach; .. dann erzähle ich es Dir <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>zu overflow: Es ist nirgends(!) beschrieben <strong>wie</strong> sie arbeitet, es ist lediglich definiert <strong>was</strong> sie tun soll; nämlich das übergebende Zeichen und alle im Buffer stehenden - falls da welche stehen - an das unterliegende Device übergeben - im Standard steht: <code>Consumes some initial subsequence of the characters of the pending sequence.</code></p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1832475</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1832475</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Mon, 04 Jan 2010 19:36:06 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Mon, 04 Jan 2010 20:32:37 GMT]]></title><description><![CDATA[<p>Vielen Dank für deine Antwort.<br />
Mein Problem hier ist:<br />
Pseudocode</p>
<pre><code class="language-cpp">class buf {
public:
	buf() {
		if(!this-&gt;lade_dll()) { // lade_dll == 0
			// Exception...
		}
		if(!this-&gt;get_socket()) { // konnte keinen socket-descriptor bekommen
			// Exception...
		}
	}
};

class stream {
private:
	buf b;

public:
	stream()
		: b() {
	}

	stream(buffer* bptr)
		: b(bptr) {
	}
};

int main() {
   try {
      stream sout; // socket out &lt;---- Erste Try-Möglichkeit
   }
   catch(...) {
      // tu was
   }
}
</code></pre>
<p>Der Konstruktor hat keinen Rückgabewert, deshalb kann er keine Information über den Erfolg der Pufferinitialisierung per return geben.<br />
Möglichkeit Exception:<br />
Ich kann die Exception einfach nirgendwo fangen und &quot;verschlucken&quot;, um sie den Kunden nicht auf zu nötigen. Der erwartet ja keine Exceptions, wenn er nicht exceptions() aufruft. Ich kann im Stream auch kein clear(ios_base::badbit) machen, da die Exception ja schon bei der <em>Konstruktion</em> des Puffers auftritt und somit auch den Streamkonstruktor abbricht. Das geht so denke ich nicht.<br />
Ich könnte die Initialisierungsfunktion auch außerhalb des Konstruktors vom Buffer platzieren. Damit hätte ich das Exceptionproblem nicht mehr:</p>
<pre><code class="language-cpp">class buf {
public:
	buf() {
	}

	Traits::state_type init() {
		if(!load_dll) return FEHLERCODE_1;
		if(!get_socket) return FEHLERCODE_2;
		return ERFOLGSCODE;
	}
};

class stream {
private:
	buf b;

public:
	stream()
		: b() {
		state_type ret = b.init();
		switch(ret) {
			case FEHLERCODE_1: // ab hier kann man nicht mehr rausfinden, was nicht geklappt hat
			case FEHLERCODE_2:
				std::ios_base::clear(std::ios_base::badbit);
				break;
			case ERFOLGSCODE:
				// Juppi!!!!
		}
	}
};
</code></pre>
<p>Ich bin mir aber nicht schlüssig, ob man solche init()-Methoden explizit anbieten sollte. Ich finde, sie ist einfach zu sehr Teil der Implementierung und der Aufruf ist bei jeder Pufferverwendung erforderlich, dass der Ctor sie doch lieber automatisch aufrufen sollte, um das Interface einfach zu halten und den echten Sinn der Initialisierung zu wahren. Der Ctor hat nur eben keine Rückgabewerte und die Exceptions fliegen bei ihm durch, da die Member initialisuert werden, bevor ich im Stream-Ctor irgendwas machen kann.</p>
<blockquote>
<p>Falls Du den spezifischen Fehler weiterleiten möchtest, so musst Du im stream (std::ostream oder std::istream) mit stream.exception(std::ios_base::badbit) das Exception-Flag so setzen, dass eine Exception des streambufs weitergeleitet wird</p>
</blockquote>
<p>Wie müsste das dann ungefähr aussehen?</p>
<p>PS: Danke für deine Hilfe. :xmas2: Das Thema finde ich nicht sehr einfach und es gibt kaum noch jemanden, der mir hier helfen kann.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1832513</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1832513</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Mon, 04 Jan 2010 20:32:37 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Tue, 05 Jan 2010 11:40:38 GMT]]></title><description><![CDATA[<p>Ich weiß nicht, ob du es schon kennst -)</p>
<p>Es gibt noch die Möglichkeit das Schlüsselwort 'try' um den gesamten Block des Konstruktors (inkl. Initialisierungsliste) zu setzen:</p>
<pre><code class="language-cpp">stream()
try
 : b()
{
}
catch(...)
{
  ...
}
</code></pre>
<p>s.a. <a href="http://www.cs.technion.ac.il/~imaman/programs/throwingctor.html" rel="nofollow">http://www.cs.technion.ac.il/~imaman/programs/throwingctor.html</a><br />
Schlüsselbegriff dafür: function-try-block</p>
<p>Beachte aber, daß du auf jeden Fall eine Exception werfen mußt bzw. der Compiler automatisch die Exception weiterwirft. Du kannst dann aber noch auf die geworfene Exception des Memberobjekts reagieren.</p>
<p>Ich hoffe, ich habe dein Problem richtig verstanden?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1832838</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1832838</guid><dc:creator><![CDATA[Th69]]></dc:creator><pubDate>Tue, 05 Jan 2010 11:40:38 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Tue, 05 Jan 2010 16:51:42 GMT]]></title><description><![CDATA[<p>Hm... sehr komisch, dieses Sprachfeature kannte ich noch gar nicht, danke. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /><br />
Aber leider würde das nicht mein Problem lösen, da Streams per default keine Exceptions werfen (nur mit Aufruf von exceptions()), der Catch-Block jedoch weiterwirft und nicht verschlucken kann. Ich bin dank Forensuche aber auf ein Buchexzerpt des von Werner genannten Buches gestoßen, zu finden auf <a href="http://www.angelikalanger.com/IOStreams/Excerpt/excerpt.htm" rel="nofollow">http://www.angelikalanger.com/IOStreams/Excerpt/excerpt.htm</a><br />
Das schaue ich mir erst mal an und melde mich hier noch mal, wenn's Probleme gibt oder fertig ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1833096</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1833096</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Tue, 05 Jan 2010 16:51:42 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Tue, 05 Jan 2010 21:04:43 GMT]]></title><description><![CDATA[<p>Das Problem 'eine Exception im Konstruktor abzufangen' hat zunächst mal nichts mit streambuf und streams zu tun.<br />
Du könntest aber - was die Schnittstelle zum Benutzer angeht - genauso vorgehen wie beim std::fstream.</p>
<p>Was Du auf jeden Fall benötigst ist die vom std::streambuf (bzw. basic_streambuf - das unterscheide ich hier mal nicht) abgeleitete Klasse; also den basic_sockbuf. Dieser Klasse kannst Du einen Konsruktor verpassen, der zunächst 'nichts' tut und zusätzlich eine Methode open (oder connect), die den Socket aktiviert. Das entspricht dem std::basic_filebuf mit der Methode open(..).<br />
Einen eigenen Stream zu schreiben ist unnötig, da std::ostream (bzw. std::basic_ostream) für die Ausgabe und std::istream für die Eingabe bereits zur Verfügung stehen. Um den Anwender die Arbeit zu vereinfachen kann man aber einen von std::basic_ostream abgeleitet Stream anbieten (für die Eingabe entsprechende basic_istream), der nichts tut, außer die Klasse basic_sockbuf als Member aufzumehmen und die Methoden is_open und open (bzw. connect &amp; is_connected) anzubieten. Das wäre das Pendant zu std::basic_ofstream (bzw. std::basic_ifstream). Z.B. basic_o(i)socketstream.</p>
<p>Falls basic_sockbuf::open eine Exception wirft, wird diese im Body von basic_o(i)socketstream wieder gefangen und der rdbuf() wird nicht gesetzt, bleibt also bei NULL. Die Methode basic_osocketstream::is_open() fragt jetzt lediglich den rdbuf() des o(i)streams ab, ist dieser !=0, so wird true zurückgeliefert. Damit hat der Anwender eine Schnittstelle, wie bei std::fstream und es wird ihm auch keine Exception um die Ohren gehauen, wenn er dies nicht explicit einschaltet.</p>
<p>Als Buffer würde ich einfach einen std::vector&lt; char_type &gt; als Member in basic_sockbuf verwenden, statt von der Klasse stream_resource abzuleiten.</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1833295</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1833295</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Tue, 05 Jan 2010 21:04:43 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Tue, 05 Jan 2010 21:30:29 GMT]]></title><description><![CDATA[<p>Klar, das mit open ginge ja problemlos. Mein Problem steckt aber in der Initialisierung. Filebufs bekommen ihre Deskriptoren durch open(), das connect()-Äquivalent einer Clientsocket-Variante. Der socket-Deskriptor kommt aber von der Funktion socket(), unter Win kommt sogar noch eine DLL-Initialisierung vor. Würde ich den Konstruktor leer lassen, diese Initialisierungen somit explizit anbieten, entspricht das der 2. Variante in meinem obigen Post.<br />
Dort verliere ich hingegen die Fehlerinformation. badbit - toll, das sagt dem Programmierer, hat nicht geklappt. Bloß was? errno, GetLastError() (unter Win WSAGetLastError()) ist dort aufschlussreicher. Ich glaube, ich werde deshalb dem Streampuffer auch Zustandsflags geben, der Nummer von GetLastError(), und im Stream eine kurze Methode definieren, vllt. sogar ein Exception-Schmeißer á la:</p>
<pre><code class="language-cpp">class stream {
   // ...
   void last_error() throw(net_error) {
      switch(rdbuf().error_flag) {
          case 0: return; // alles okay
          case 0xDEADBEEF: throw net_error(0xDEADBEEF, &quot;error loading dll&quot;);
          // ...
       }
    }
};

int main() {
    stream s; // macht init, setzt evtl. stream auf badbit, puffer auf getlasterror
    ...
    if(!s) {
       try { 
         s.last_error();
       }
       catch(net_error&amp; e) {
           log(&quot;Fehler: &quot; + e.what() + &quot;\nNummer: &quot; + e.number());
       }
     }
}
</code></pre>
<p>So kann man zusätzlich noch genauere Informationen anbieten, Exception auf Nachfrage so zu sagen, ich denke, das nötigt sich auch nicht auf, fail() o. operator!() können dem User ja auch reichen.<br />
Ich mache jetzt erst mal weiter, die Clientseite fertig. Werner, dir besonders vielen Dank für die Hilfe. Ich mache die Clientseite fertig und erstelle noch ein paar hüppsche Manipulatoren dazu. Ich werde mich spätestens wieder melden, wenn ich Leseoperationen machen will. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /> (Stichwort (A)synchrones Multiplexing).</p>
<p>Den Thread grabe ich dann wieder aus.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1833311</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1833311</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Tue, 05 Jan 2010 21:30:29 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Tue, 05 Jan 2010 21:37:12 GMT]]></title><description><![CDATA[<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Klar, das mit open ginge ja problemlos. Mein Problem steckt aber in der Initialisierung. Filebufs bekommen ihre Deskriptoren durch open(), das connect()-Äquivalent einer Clientsocket-Variante. Der socket-Deskriptor kommt aber von der Funktion socket(), unter Win kommt sogar noch eine DLL-Initialisierung vor. Würde ich den Konstruktor leer lassen, diese Initialisierungen somit explizit anbieten, entspricht das der 2. Variante in meinem obigen Post.<br />
Dort verliere ich hingegen die Fehlerinformation. badbit - toll, das sagt dem Programmierer, hat nicht geklappt. Bloß was? errno, GetLastError() (unter Win WSAGetLastError()) ist dort aufschlussreicher.</p>
</blockquote>
<p>Sicher .. es verbiete Dir doch niemand, der Klasse basic_sockbuf und der Klasse basic_o(i)socketstream eine GetLastErrorMsg() -Methode zu verpassen. Dort könnte dann der Text der zuletzt gefangenen Exception hinterlegt sein.<br />
Vielleicht verstehe ich Dein Problem auch nicht so ganz.</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1833322</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1833322</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Tue, 05 Jan 2010 21:37:12 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Tue, 05 Jan 2010 21:41:36 GMT]]></title><description><![CDATA[<p>Schon okay, ich mache es jetzt so. Wenn es am Ende nicht gut sein sollte, werde ich es eben bereuhen und verbessern. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1833332</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1833332</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Tue, 05 Jan 2010 21:41:36 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Tue, 05 Jan 2010 21:53:11 GMT]]></title><description><![CDATA[<p>Noch mal einen Tipp, da ich gerade Deinen anderen Thread hier gesehen habe.<br />
Dieses <a href="http://www.amazon.de/Pattern-orientierte-Software-Architektur-nebenl%C3%A4ufige-vernetzte-Objekte/dp/3898641422/ref=sr_1_4?ie=UTF8&amp;s=books&amp;qid=1262727818&amp;sr=8-4" rel="nofollow">Buch über neben-läufige Pattern</a> könnte für Dich interessant sein. Im Netz gibt es auch einiges zum <a href="http://www.cs.wustl.edu/~schmidt/patterns-ace.html" rel="nofollow">Design von Programmen die viele Anfragen verarbeiten müssen</a> - insbesondere zum <a href="http://www.cs.wustl.edu/~schmidt/PDF/proactor.pdf" rel="nofollow">Proactor-Pattern</a></p>
<p>Und ansonsten liefert <a href="http://www.boost.org/doc/libs/1_41_0/doc/html/boost_asio.html" rel="nofollow">boost.asio</a> eigentlich schon alles. Selbst wenn man es nicht benutzt, als Vorlage taugt es alle mal.</p>
<p>So damit bist Du eine Weile beschäftigt <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /><br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1833343</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1833343</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Tue, 05 Jan 2010 21:53:11 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Sat, 09 Jan 2010 18:52:58 GMT]]></title><description><![CDATA[<p>Okay, ich habe schon ma etwas weiter gemacht. Mei Interface schaut so aus:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &quot;ionstream.hpp&quot;

int main() {
	try {
		net::endpoint server(&quot;127.0.0.1&quot;, 55555);
		net::onstream nout(server, net::tcp);

		if(!nout)
			nout.error();

		nout &lt;&lt; &quot; ahahl&quot; &lt;&lt; std::flush;
		for(;;);

	}
	catch(const net::net_error&amp; e) {
		std::cerr &lt;&lt; e.what() &lt;&lt; &quot;\nError code: &quot; &lt;&lt; e.number() &lt;&lt; '\n';
	}

}
</code></pre>
<p>Jetzt habe ich eine Frage:<br />
Wie funktioniert die Kommunikation zwischen Stream und Puffer beim operator &lt;&lt;()? Ich habe die Überladung leider nicht gefunden, ich nehme aber an, dass der Operator buffer.xsputn() aufruft, oder? Wenn das der Fall ist, was muss xsputn() (von meinem Puffer überladen) zurückgeben, damit der Stream auf badbit oder failbit gesetzt wird? Standardmäßig ist es ja die Anzahl der in den internen Puffer geschriebenen Zeichen, unabhängig davon, ob ein overflow() dazwischenkommt. Wie bewerkstellige ich das? Sind die beiden Methoden so okay?</p>
<pre><code class="language-cpp">virtual std::streamsize xsputn(const Ch* p, std::streamsize n) {
	setp(pbuf, pbuf + buflen());
	std::streamsize i;
	for(i = 0; i &lt; n; i++)
		if(sputc(p[i]) == -1)  // löst irgendwann overflow() aus
			return 0; // ein Fehler ist passiert, bloß wie benachrichtigen?
	return i;
}

virtual int_type overflow(int_type c = Tr::eof()) {
	int_type result = ::send(handle, pbase(), pptr() - pbase(), 0); // den bis jetzt beschriebenen Puffer senden
	bstate = WSAGetLastError(); // Pufferzustand retten
	seekpos(0, std::ios_base::out); // pptr() auf 0 zurückstellen
	sputc(c); // neues Zeichen in den Puffer schreiben
	return result; // bei Fehler -1, sonst 0
}
</code></pre>
<p>Danke :xmas2:</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1835849</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1835849</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Sat, 09 Jan 2010 18:52:58 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Sun, 10 Jan 2010 11:47:44 GMT]]></title><description><![CDATA[<p>Ach und die zweite Frage betrifft setbuf().<br />
Wie genau arbeitet die Funktion für gewöhnlich? Etwa so?</p>
<pre><code class="language-cpp">virtual basic_sockbuf&lt;Ch, Tr&gt;* setbuf(Ch* p, std::streamsize n) {
	std::cout &lt;&lt; &quot;PUFFER SETZEN: &quot; &lt;&lt; p &lt;&lt; std::endl;
	setp(p, p + n); // put-area setzen
	setg(p, p, p + n); // get-area setzten
	return this;
}
</code></pre>
<p>Wird die put/get-Area eigentlich nicht erst gesetzt, wenn eine Put/Get-Operation aufgerufen wird? Ich stehe da leider etwas auf dem Schlach. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1836153</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1836153</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Sun, 10 Jan 2010 11:47:44 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Tue, 12 Jan 2010 18:26:29 GMT]]></title><description><![CDATA[<p>Kann mir da niemand helfen? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
<p>Ich will nur erreichen, dass das erst mal funktioniert:</p>
<pre><code class="language-cpp">char buf[] = &quot;Hello&quot;; // = 6 byte
net::basic_onstream nout;
nout.rdbuf()-&gt;pubsetbuf(buf, 6); // --&gt; setbuf() --&gt; setp() UND setg() ?
nout &lt;&lt; &quot;Ich bin eine Nachricht&quot;; // operator &lt;&lt;() --&gt; sputn() --&gt; xsputn() --&gt; sputc() --&gt; overflow() bei 'i'
</code></pre>
<p>Was genau verursacht setbuf()? Wird die get-Area UND die put-Area neu gesetzt, nicht aber pptr(), gptr(), eptr() usw.? Werden die dann erst durch setp/setg bei Aufrufen von xsgetn() und xsputn() beeinflusst?</p>
<p>Und da hätte ich auch den nächsten Salad: der physikalische Puffer (Ch*) ist ein Heap-Array, welches im Destruktor frei gegeben wird. Wenn ich nun in setbuf() den Ch*-Zeiger auf das per Parameter erhaltene neue Ch*-Array umbiege, wird natürlicherweise das vom Destruktor mit delete [] gelöscht. Nur: wer garantiert, dass das kein Stack-Array ist? delete auf Stack ist ja undefiniert. Muss ich dann 2 Puffer anlegen (Ch* default_buf, *user_buf)?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1837764</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1837764</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Tue, 12 Jan 2010 18:26:29 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Tue, 12 Jan 2010 21:57:09 GMT]]></title><description><![CDATA[<p>Oh hallo - gleich drei Postings und so viele Fragen ...</p>
<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Wie funktioniert die Kommunikation zwischen Stream und Puffer beim operator &lt;&lt;()? Ich habe die Überladung leider nicht gefunden, ich nehme aber an, dass der Operator buffer.xsputn() aufruft, oder?</p>
</blockquote>
<p>Nein - das ist etwas anders. Solange Du nicht genau weißt, wie es funktioniert, vergisst bitte 'xsputn' zunächst mal.</p>
<p>Ad aCTa schrieb:</p>
<blockquote>
<p>... was muss xsputn() (von meinem Puffer überladen) zurückgeben, damit der Stream auf badbit oder failbit gesetzt wird?</p>
</blockquote>
<p>Mit der Methode overflow allein, kannst Du einen überladenen Streambuf realisieren. Mit dem Zeichen, das nicht mehr in den internen Buffer (s.u.) geschrieben werden kann, wird streambuf::overflow aufgerufen. Kommt die Methode mit EOF zurück, so liegt ein Fehler vor und der Stream, der den Buffer nutzt, setzt das failbit.</p>
<p>Da Du aber auf jeden Fall einen Speicherbereich mit mehr als einem Zeichen für die Socketkommunikation benötigst, gehe ich gleich einen Schritt weiter.</p>
<p>Du benötigst in dem basic_sockbuf ein Stück Memory (den internen Buffer), wo man Zeichen hineinschreiben kann, am besten als 'Member' des basic_sockbuf. Der Einfachheit halber nehme ich mal an, dass da ein std::vector&lt; char_type &gt; existiert. Dieser wird als interner Buffer benutzt. Das sieht im Prinzip so aus:</p>
<pre><code class="language-cpp">#include &lt;streambuf&gt;
#include &lt;vector&gt;

template&lt; typename Ch, typename Tr = std::char_traits&lt; Ch &gt; &gt;
class basic_sockbuf : public std::basic_streambuf&lt; Ch, Tr &gt;
{
public:
    basic_sockbuf()
        : m_buf( 400 ) // einfach mal 400 Zeichen reservieren
    {
        setp( &amp;m_buf[0], &amp;m_buf[0] + m_buf.size() - 1 ); // Put-Pointer auf den Buffer; ein Zeichen Platz lassen
    }
protected:
    virtual int_type overflow( int_type m = traits_type::eof() )
    {
        const char* pend = pptr();
        if( !traits_type::eq_int_type( m, traits_type::eof() ) )
        {
            // es wurde noch ein Zeichen übergeben
            *pptr() = traits_type::to_char_type( m ); // hinten anfügen
            ++pend;
        }
        if( !senddata( pbase(), pend ) )
            return traits_type:eof(); // Fehler
        setp( &amp;m_buf[0], &amp;m_buf[0] + m_buf.size() - 1 ); // Put-Pointer neu setzen
        return traits_type::not_eof( m ); // ok
    }

private:
    bool senddata( const char_type* first, const char_type* last )
    {
        // ... hier alle Zeichen im Intervall [first,last) über den Socket schicken
        return true; // ok
    }
    // --  Members
    std::vector&lt; char_type &gt; m_buf;
};
</code></pre>
<p>Das bezeichnet man als eine gepufferte Ausgabe. Wie Du siehst benötigt man dazu weder setbuf (hat damit nichts zu tun) noch xsputn.</p>
<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Mei Interface schaut so aus: ..</p>
</blockquote>
<p>Es sollte ungefähr so aussehen:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &quot;sockbuf.hpp&quot;

int main() {
    try {
        basic_sockbuf&lt; char &gt; server; // (&quot;127.0.0.1&quot;, 55555); Parameter nach Bedarf hinzufügen
        std::ostream nout(&amp;server); // Du brauchst keinen(!) eigenen ostream

        nout &lt;&lt; &quot; ahahl&quot; &lt;&lt; std::flush;
        for(;;);

    }
    catch(const net::net_error&amp; e) { // das könnte von 'basic_sockbuf&lt; char &gt;' geworfen werden
        std::cerr &lt;&lt; e.what() &lt;&lt; &quot;\nError code: &quot; &lt;&lt; e.number() &lt;&lt; '\n';
    }
    return 0;
}
</code></pre>
<p>Damit das std::flush funktioniert, musst Du noch das basic_streambuf::sync überladen.</p>
<p>Danach sollte das Senden von Daten grundsätzlich funktionieren.</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1837900</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1837900</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Tue, 12 Jan 2010 21:57:09 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Wed, 13 Jan 2010 18:23:12 GMT]]></title><description><![CDATA[<p>Erst mal vielen Dank. Um das mit dem Overflow zu klären:</p>
<pre><code class="language-cpp">// Aufruf von overflow durch basic_streambuf&lt;Ch, Tr&gt;::sputc, wenn
// pptr() - pbase() = 1, also noch ein Zeichen in den Puffer passt
virtual int_type overflow(int_type c = Tr::eof()) {
	const Ch* end = pptr();
	if(!Tr::eq_int_type(c, Tr::eof())) { // letztes Zeichen in den Puffer lesen, voll
		*pptr() = Tr::to_char_type(c);
		++end;
	}
	if(::send(handle, pbase(), end - pbase(), 0) == -1) {
		bstate = WSAGetLastError();
		return Tr::eof();
	}
	setp(&amp;pbuf[0], &amp;pbuf[0] + pbuf.size() - 1);
	return Tr::not_eof(c);
}
</code></pre>
<p>Das sehe ich so richtig, oder?<br />
Ich habe meinen Stream jetzt auch mit Manipulatoren getestet und den sockbuf mal für std::cout gesetzt, klappt alles wunderbar. Ich habe den Stream einfach wegen besserer Fehlerbehandlung erstellt, und auch wegen der TCP/UDP-Steuerung, das kann man einfach nicht vernünftig mit std::basic_ostream alleine implementieren. Der vector zum speichern ist mir noch ein Dorn im Auge. Wenn man den Puffer (und dessen Größe) manuell setzten will, was im Netzwerk vorkommen kann, wegen lahmer Bandbreite etc., sollte pubsetbuf funktionieren. Ich muss mir da noch was einfallen lassen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1838348</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1838348</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Wed, 13 Jan 2010 18:23:12 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Wed, 13 Jan 2010 21:17:42 GMT]]></title><description><![CDATA[<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Erst mal vielen Dank. Um das mit dem Overflow zu klären:</p>
<pre><code class="language-cpp">// Aufruf von overflow durch basic_streambuf&lt;Ch, Tr&gt;::sputc, wenn
// pptr() - pbase() = 1, also noch ein Zeichen in den Puffer passt
virtual int_type overflow(int_type c = Tr::eof()) {
	const Ch* end = pptr();
	if(!Tr::eq_int_type(c, Tr::eof())) { // letztes Zeichen in den Puffer lesen, voll
		*pptr() = Tr::to_char_type(c);
		++end;
	}
	if(::send(handle, pbase(), end - pbase(), 0) == -1) {
		bstate = WSAGetLastError();
		return Tr::eof();
	}
	setp(&amp;pbuf[0], &amp;pbuf[0] + pbuf.size() - 1);
	return Tr::not_eof(c);
}
</code></pre>
<p>Das sehe ich so richtig, oder?</p>
</blockquote>
<p>ich denke - ja. Nur der Kommentar ist falsch - wenn 'pptr() - pbase() == 1', dann liegt genau schon ein Zeichen im Buffer. Mit epptr()-pptr() bekommt man den freien Bereich im internen Buffer, wenn der 0 ist - also epptr()==pptr() - dann wird vom stream overflow gerufen.</p>
<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Ich habe den Stream einfach wegen besserer Fehlerbehandlung erstellt, und auch wegen der TCP/UDP-Steuerung, das kann man einfach nicht vernünftig mit std::basic_ostream alleine implementieren.</p>
</blockquote>
<p>Wenn ich das lese, bin ich mir gar nicht sicher, ob Du das mit den Streams richtig verstanden hat. Ein Stream selbst hat per se nichts mit der Fehlerbehandlung z.B. einer Socketverbindung zu tun. Auch die TCP/UDP-Steuerung ist Sache des basic_sockbuf. Ein eigener Stream macht Sinn, wenn er z.B. von std::ostream abgeleitet ist, den socketbuf als Member beinhaltet und dessen spezifische Methoden durchleitet. Wenn Du das so meinst, was ist dann aber net::endpoint?<br />
Wie sieht denn Dein net::onstream aus? Von was ist er abgeleitet?</p>
<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Der vector zum speichern ist mir noch ein Dorn im Auge. Wenn man den Puffer (und dessen Größe) manuell setzten will, was im Netzwerk vorkommen kann, wegen lahmer Bandbreite etc., sollte pubsetbuf funktionieren. Ich muss mir da noch was einfallen lassen.</p>
</blockquote>
<p>Der vector war nur ein Beispiel, es ist natürlich prinzipiell jedes Stück Memory möglich; es ist schlicht praktisch, wenn das innerhalb des socketbuf liegt. Aber auch hier verstehe ich Deine Anforderung nicht so ganz.</p>
<p>Nachtrag zu sync. Das kann so aussehen:</p>
<pre><code class="language-cpp">virtual int sync()
    {
        return traits_type::eq_int_type( overflow(), traits_type::eof() )? -1: 0; // -1: Fehler; 0: Ok
    }
</code></pre>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1838464</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1838464</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Wed, 13 Jan 2010 21:17:42 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Wed, 13 Jan 2010 22:08:50 GMT]]></title><description><![CDATA[<p>Naja, mein sync() sieht eigentlich nur so aus:</p>
<pre><code class="language-cpp">virtual int_type sync() {
	return overflow();
}
</code></pre>
<p>Wenn ein Fehler auftritt und overflow() Tr::eof() zurückgibt, kann ich das auch gleich weiterreichen.</p>
<blockquote>
<p>&gt; Auch die TCP/UDP-Steuerung ist Sache des basic_sockbuf.</p>
</blockquote>
<p>Habe mich etwas unglücklich ausgedrückt. Ich will nur die Informationen an den Puffer weitergeben. Einen Endpunkt hat nun mal jede Verbindung, deshalb habe ich ihn extern einmal repräsentiert. Der Konstruktor muss nun einen Endpunkt aufnehmen können und zusätzlich ein paar Zusatzspezifikationen:</p>
<pre><code class="language-cpp">template &lt;typename Ch, typename Tr = std::char_traits&lt;Ch&gt; &gt;
class basic_onstream : public std::basic_ostream&lt;Ch, Tr&gt; {
public:
	typedef basic_sockbuf&lt;Ch, Tr&gt; buf_type;

	basic_onstream()
		: std::basic_ostream&lt;Ch, Tr&gt;(&amp;buffer) {
	}

	basic_onstream(const std::basic_streambuf&lt;Ch, Tr&gt;* b)
		: basic_ostream&lt;Ch, Tr&gt;(b), buffer(*b) {
	}

	// default: net::tcp
	explicit basic_onstream(const endpoint&amp; ep, const sockmodes&amp; sm = sockmodes(0xF0F0))
		: std::basic_ostream&lt;Ch, Tr&gt;(&amp;buffer) {
			// basic_sockbuf initialisieren, Socketmodus weiterreichen, Flags setzten etc.
	}

	// noch etwas anderes....

private:
	// kopieren verhindern etc.
	buf_type buffer;
};
</code></pre>
<p>Die Sockmodes sin ähnlich ios_base::in/out, nur noch um Eigenschaften wie TCP und UDP erweitert. Die Konstruktoren sind einfach zu speziell. Ich denke so wie fstream extra existieren muss, muss auch ein socket_stream existieren, alleine schon wegen der Konstruktoren.</p>
<p>Was mich hierbei etwas stört ist das doppelte Vorhandensein des Puffers. Einmal speichere ich einen und den selben als Zeiger in der Basisklasse, einmal habe ich selber einen da. Es ist das Slicing-Problem: wenn ich buffer nicht als Element in meiner Klasse hätte, müsste ich rdbuf() anwenden. Da das aber einen Zeiger auf basic_streambuf zurückgibt, entfallen alle speziellen Methoden meines eigenen Puffers (das Interface ist logischerweise nicht da).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1838501</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1838501</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Wed, 13 Jan 2010 22:08:50 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Wed, 13 Jan 2010 22:17:51 GMT]]></title><description><![CDATA[<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Naja, mein sync() sieht eigentlich nur so aus:</p>
<pre><code class="language-cpp">virtual int_type sync() {
	return overflow();
}
</code></pre>
<p>Wenn ein Fehler auftritt und overflow() Tr::eof() zurückgibt, kann ich das auch gleich weiterreichen.</p>
</blockquote>
<p>Nicht ganz, da sync protected ist.<br />
Und lt. Standard liefert sync -1 im Fehlerfall und 0, wenn alles ok ist.</p>
<p>Ad aCTa schrieb:</p>
<blockquote>
<p>Was mich hierbei etwas stört ist das doppelte Vorhandensein des Puffers.</p>
</blockquote>
<p>Ich sehe immer nur einen Puffer. Wo ist da was doppelt?</p>
<p>Dein net::onstream ist das was ich meinte - das sollte ok sein.</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1838507</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1838507</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Wed, 13 Jan 2010 22:17:51 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Thu, 14 Jan 2010 13:09:02 GMT]]></title><description><![CDATA[<blockquote>
<p>&gt; Ich sehe immer nur einen Puffer. Wo ist da was doppelt?</p>
</blockquote>
<p>Na die Basisklasse hat ja auch einen. Irgendwo muss sie irgendeinen basic_streambuf&lt;&gt;*-Member haben, der von rdbuf() zurückgegeben wird. Ich würde ja gerne genau diesen internen Puffer benutzen (der mit dem Member identisch ist), aber das geht ja eben (wegen Slicing-Problem) nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1838744</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1838744</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Thu, 14 Jan 2010 13:09:02 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Thu, 14 Jan 2010 17:35:34 GMT]]></title><description><![CDATA[<p>Ad aCTa schrieb:</p>
<blockquote>
<blockquote>
<p>&gt; Ich sehe immer nur einen Puffer. Wo ist da was doppelt?</p>
</blockquote>
<p>Na die Basisklasse hat ja auch einen. Irgendwo muss sie irgendeinen basic_streambuf&lt;&gt;*-Member haben, der von rdbuf() zurückgegeben wird. Ich würde ja gerne genau diesen internen Puffer benutzen (der mit dem Member identisch ist), aber das geht ja eben (wegen Slicing-Problem) nicht.</p>
</blockquote>
<p>Welche Basisklasse meinst Du? std::basic_streambuf&lt;&gt; hat keinen Buffer nicht ein Byte.<br />
Der Stream (z.B.: std::ostream) hat einen Pointer (nicht Komposition) auf einen std::basic_streambuf&lt;&gt;, das ist ein Objekt und kein Puffer im Sinne eines Memory-Buffers. Diesen Pointer auf das Buffer-Objekt kann man mit rdbuf() abholen. (Bem.: rdbuf() erbt jeder Stream von std::basic_ios&lt;&gt;)<br />
Ein Stream selbst puffert nie ein Zeichen, er arbeitet eher wie ein Durchlauferhitzer.</p>
<p>Ein Slicing-Problem mit Stream oder Buffer kann es hier gar nicht geben, da weder die Streams noch die Buffer kopierbar bzw. zuweisbar sind (zumindest vom Sinn her). Sollten sie es rein formal sein, ist das eher als Fehler zu sehen.</p>
<p>Gruß<br />
Werner</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1838954</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1838954</guid><dc:creator><![CDATA[Werner Salomon]]></dc:creator><pubDate>Thu, 14 Jan 2010 17:35:34 GMT</pubDate></item><item><title><![CDATA[Reply to Funktionsweise von IO-Streams on Thu, 14 Jan 2010 18:35:04 GMT]]></title><description><![CDATA[<p>Mit Puffer meine ich ja den Streambuf. Dass man sich den mit rdbuf() abholt etc. ist mir ja bewusst, ich kenne Sinn und Bedeutung von Stream (Formatierung/Kommunikation) und Puffer (Speicher/Physikalische Verbindung).</p>
<p>Wenn mein streambuf eine neue Methode dazubekommt (meinetwegen open()), dann kann ich diese Methode nur über einen Zeiger dieser selben Klasse aufrufen. Wenn ich aber nun rdbuf() in meinem Stream benutze, um Methoden wie connect/init/etc im Streamkonstruktor aufzurufen, werde ich scheitern, da rdbuf() einen Zeiger auf die Basisklasse zurückgibt, bei dem es diese Methoden nicht gibt, obwohl der Zeiger selbst auf ein Objekt zeigt, welche sie hat (dank statischer Bindung). Das meine ich mit slicing.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1838972</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1838972</guid><dc:creator><![CDATA[Ad aCTa]]></dc:creator><pubDate>Thu, 14 Jan 2010 18:35:04 GMT</pubDate></item></channel></rss>