<?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[Socket nicht blockend lesen]]></title><description><![CDATA[<p>Hallo,<br />
ich habe hier einen Socket (um genau zu sein einen serial_port) und will eine Klasse schreiben mit der es möglich ist nicht blockend zu lesen, sprich alles was da ist soll zurück gegeben werden und fertig. Das scheint jedoch deutlich schwerer zu sein als zunächst gedacht.</p>
<pre><code class="language-cpp">#ifndef BOOSTCOMPORT_HPP_
#define BOOSTCOMPORT_HPP_

#include &lt;boost/asio.hpp&gt;
#include &lt;string&gt;
#include &lt;iostream&gt;

using namespace std;

class BoostComPort
{
public:
	BoostComPort();
	~BoostComPort();
	int open(std::string port, int baud);
	int close();
	bool isOpended();
	int write(char* Data, unsigned int Length);
	int read(char* data, unsigned int length, bool blocking=false);
	boost::system::error_code&amp; getLastError();

private:
	void onPortRead(const boost::system::error_code&amp; error, std::size_t bytes_transferred);

	char* data;
	std::size_t bytes_transferred;
	boost::asio::io_service io_service;
	boost::asio::serial_port serialPort;
	boost::system::error_code ec;
	boost::system::error_code lastError;
protected:

};

#endif
</code></pre>
<pre><code class="language-cpp">#include &quot;BoostComPort.hpp&quot;
#include &lt;boost/bind.hpp&gt;

BoostComPort::BoostComPort():
data(NULL),
serialPort(io_service)
{
	lastError.clear();
}

BoostComPort::~BoostComPort()
{
	serialPort.close();
}

int BoostComPort::open(std::string port, int baud)
{
	if(serialPort.is_open())
		serialPort.close();
	serialPort.open(port);
	boost::asio::serial_port_base::baud_rate baudRate(baud);
	serialPort.set_option(baudRate);
	char* tmp=new char[100]; // 5MBi of temporary buffer to clean the system buffers
	int read;
	do
	{
		read=this-&gt;read(tmp, 100, false);
	} while(read&gt;0);
	delete[] tmp;
	return 0;
}

boost::system::error_code&amp; BoostComPort::getLastError()
{
	return lastError;
}

int BoostComPort::close()
{
	return 0;
}

bool BoostComPort::isOpended()
{
	return serialPort.is_open();
}

int BoostComPort::write(char* data, unsigned int length)
{
	size_t written=boost::asio::write(serialPort, boost::asio::buffer(data, length), boost::asio::transfer_all(), ec);
	if(written!=length)
		return -1;
	return 0;
}

int BoostComPort::read(char* data, unsigned int length, bool blocking)
{
	// start async read
	serialPort.async_read_some(boost::asio::buffer(data, length), boost::bind(&amp;BoostComPort::onPortRead, this, _1, _2));
	bytes_transferred=-1;
	io_service.poll(); // read the data
	// cancel all pending operations
	serialPort.cancel();
	return bytes_transferred;
}

void BoostComPort::onPortRead(const boost::system::error_code&amp; error, std::size_t bytes_transferred)
{
	if(error==0)
	{
		this-&gt;bytes_transferred=bytes_transferred;
		cout&lt;&lt;&quot;Read some bytes...&quot;&lt;&lt;endl;
	}
	else if(error!=boost::asio::error::operation_aborted)  // not cancelled
	{
		cerr&lt;&lt;&quot;BoostComPort::onPortRead(): Unable to read from com port with error: &quot;&lt;&lt;endl;
		cerr&lt;&lt;&quot;BoostComPort::onPortRead():   Error message: &quot;&lt;&lt;error.message()&lt;&lt;endl;
		cerr&lt;&lt;&quot;BoostComPort::onPortRead():   Error code: &quot;&lt;&lt;error&lt;&lt;endl;
		lastError=ec;
	}
}
</code></pre>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &quot;BoostComPort.hpp&quot;

using namespace std;

int main()
{
	BoostComPort comport;
	comport.open(&quot;/dev/ttyUSB0&quot;, 19200);
	for(int i=0; i&lt;3; i++)
	{
		if(comport.write((char*)&quot;test 1234567890&quot;, 15)==-1)
			cout&lt;&lt;&quot;Failed to write data to port!&quot;&lt;&lt;endl;
	}
	for(unsigned int i=0; i&lt;0xffffff; i++);
	char* data=new char[100];
	memset(data, 0, 100);
	int read=comport.read(data, 15);
	cout&lt;&lt;&quot;read: &quot;&lt;&lt;read&lt;&lt;endl;
	cout&lt;&lt;&quot;data: &quot;&lt;&lt;data&lt;&lt;endl;
	memset(data, 0, 100);
	read=comport.read(data, 15);
	cout&lt;&lt;&quot;read: &quot;&lt;&lt;read&lt;&lt;endl;
	cout&lt;&lt;&quot;data: &quot;&lt;&lt;data&lt;&lt;endl;
	memset(data, 0, 100);
	read=comport.read(data, 15);
	cout&lt;&lt;&quot;read: &quot;&lt;&lt;read&lt;&lt;endl;
	cout&lt;&lt;&quot;data: &quot;&lt;&lt;data&lt;&lt;endl;
	memset(data, 0, 100);
	read=comport.read(data, 15);
	cout&lt;&lt;&quot;read: &quot;&lt;&lt;read&lt;&lt;endl;
	cout&lt;&lt;&quot;data: &quot;&lt;&lt;data&lt;&lt;endl;
	return 0;
}
</code></pre>
<p>Soweit mein Code, Ausgabe sieht so aus:</p>
<pre><code>Read some bytes...
read: 15
data: test 1234567890
read: -1
data: test 1234567890
read: -1
data: test 1234567890
read: -1
data:
</code></pre>
<p>Kann mir jemand sagen warum er bei den ersten drei Lesevorgängen zwar etwas liest, aber scheinbar die Methode onPortRead nur beim ersten mal aufruft? Daten stehen ja im Buffer drin. Und da er beim letzten mal dann keine Daten mehr drin stehen hat würde ich mal davon ausgehen, dass er alle im Systempuffer vorhanden Daten bei den ersten drei mal gelesen hat, mir diese jedoch nicht gibt bzw. mir nicht mitteilt, dass sie im Puffer stehen.</p>
<p>Ach ja: RX/TX sind kurzgeschlossen, also alles was ich sende kommt wieder zurück (und das funktioniert auch sicher).</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/277866/socket-nicht-blockend-lesen</link><generator>RSS for Node</generator><lastBuildDate>Tue, 25 Aug 2026 16:24:51 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/277866.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 25 Nov 2010 17:28:32 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Socket nicht blockend lesen on Thu, 25 Nov 2010 17:28:32 GMT]]></title><description><![CDATA[<p>Hallo,<br />
ich habe hier einen Socket (um genau zu sein einen serial_port) und will eine Klasse schreiben mit der es möglich ist nicht blockend zu lesen, sprich alles was da ist soll zurück gegeben werden und fertig. Das scheint jedoch deutlich schwerer zu sein als zunächst gedacht.</p>
<pre><code class="language-cpp">#ifndef BOOSTCOMPORT_HPP_
#define BOOSTCOMPORT_HPP_

#include &lt;boost/asio.hpp&gt;
#include &lt;string&gt;
#include &lt;iostream&gt;

using namespace std;

class BoostComPort
{
public:
	BoostComPort();
	~BoostComPort();
	int open(std::string port, int baud);
	int close();
	bool isOpended();
	int write(char* Data, unsigned int Length);
	int read(char* data, unsigned int length, bool blocking=false);
	boost::system::error_code&amp; getLastError();

private:
	void onPortRead(const boost::system::error_code&amp; error, std::size_t bytes_transferred);

	char* data;
	std::size_t bytes_transferred;
	boost::asio::io_service io_service;
	boost::asio::serial_port serialPort;
	boost::system::error_code ec;
	boost::system::error_code lastError;
protected:

};

#endif
</code></pre>
<pre><code class="language-cpp">#include &quot;BoostComPort.hpp&quot;
#include &lt;boost/bind.hpp&gt;

BoostComPort::BoostComPort():
data(NULL),
serialPort(io_service)
{
	lastError.clear();
}

BoostComPort::~BoostComPort()
{
	serialPort.close();
}

int BoostComPort::open(std::string port, int baud)
{
	if(serialPort.is_open())
		serialPort.close();
	serialPort.open(port);
	boost::asio::serial_port_base::baud_rate baudRate(baud);
	serialPort.set_option(baudRate);
	char* tmp=new char[100]; // 5MBi of temporary buffer to clean the system buffers
	int read;
	do
	{
		read=this-&gt;read(tmp, 100, false);
	} while(read&gt;0);
	delete[] tmp;
	return 0;
}

boost::system::error_code&amp; BoostComPort::getLastError()
{
	return lastError;
}

int BoostComPort::close()
{
	return 0;
}

bool BoostComPort::isOpended()
{
	return serialPort.is_open();
}

int BoostComPort::write(char* data, unsigned int length)
{
	size_t written=boost::asio::write(serialPort, boost::asio::buffer(data, length), boost::asio::transfer_all(), ec);
	if(written!=length)
		return -1;
	return 0;
}

int BoostComPort::read(char* data, unsigned int length, bool blocking)
{
	// start async read
	serialPort.async_read_some(boost::asio::buffer(data, length), boost::bind(&amp;BoostComPort::onPortRead, this, _1, _2));
	bytes_transferred=-1;
	io_service.poll(); // read the data
	// cancel all pending operations
	serialPort.cancel();
	return bytes_transferred;
}

void BoostComPort::onPortRead(const boost::system::error_code&amp; error, std::size_t bytes_transferred)
{
	if(error==0)
	{
		this-&gt;bytes_transferred=bytes_transferred;
		cout&lt;&lt;&quot;Read some bytes...&quot;&lt;&lt;endl;
	}
	else if(error!=boost::asio::error::operation_aborted)  // not cancelled
	{
		cerr&lt;&lt;&quot;BoostComPort::onPortRead(): Unable to read from com port with error: &quot;&lt;&lt;endl;
		cerr&lt;&lt;&quot;BoostComPort::onPortRead():   Error message: &quot;&lt;&lt;error.message()&lt;&lt;endl;
		cerr&lt;&lt;&quot;BoostComPort::onPortRead():   Error code: &quot;&lt;&lt;error&lt;&lt;endl;
		lastError=ec;
	}
}
</code></pre>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &quot;BoostComPort.hpp&quot;

using namespace std;

int main()
{
	BoostComPort comport;
	comport.open(&quot;/dev/ttyUSB0&quot;, 19200);
	for(int i=0; i&lt;3; i++)
	{
		if(comport.write((char*)&quot;test 1234567890&quot;, 15)==-1)
			cout&lt;&lt;&quot;Failed to write data to port!&quot;&lt;&lt;endl;
	}
	for(unsigned int i=0; i&lt;0xffffff; i++);
	char* data=new char[100];
	memset(data, 0, 100);
	int read=comport.read(data, 15);
	cout&lt;&lt;&quot;read: &quot;&lt;&lt;read&lt;&lt;endl;
	cout&lt;&lt;&quot;data: &quot;&lt;&lt;data&lt;&lt;endl;
	memset(data, 0, 100);
	read=comport.read(data, 15);
	cout&lt;&lt;&quot;read: &quot;&lt;&lt;read&lt;&lt;endl;
	cout&lt;&lt;&quot;data: &quot;&lt;&lt;data&lt;&lt;endl;
	memset(data, 0, 100);
	read=comport.read(data, 15);
	cout&lt;&lt;&quot;read: &quot;&lt;&lt;read&lt;&lt;endl;
	cout&lt;&lt;&quot;data: &quot;&lt;&lt;data&lt;&lt;endl;
	memset(data, 0, 100);
	read=comport.read(data, 15);
	cout&lt;&lt;&quot;read: &quot;&lt;&lt;read&lt;&lt;endl;
	cout&lt;&lt;&quot;data: &quot;&lt;&lt;data&lt;&lt;endl;
	return 0;
}
</code></pre>
<p>Soweit mein Code, Ausgabe sieht so aus:</p>
<pre><code>Read some bytes...
read: 15
data: test 1234567890
read: -1
data: test 1234567890
read: -1
data: test 1234567890
read: -1
data:
</code></pre>
<p>Kann mir jemand sagen warum er bei den ersten drei Lesevorgängen zwar etwas liest, aber scheinbar die Methode onPortRead nur beim ersten mal aufruft? Daten stehen ja im Buffer drin. Und da er beim letzten mal dann keine Daten mehr drin stehen hat würde ich mal davon ausgehen, dass er alle im Systempuffer vorhanden Daten bei den ersten drei mal gelesen hat, mir diese jedoch nicht gibt bzw. mir nicht mitteilt, dass sie im Puffer stehen.</p>
<p>Ach ja: RX/TX sind kurzgeschlossen, also alles was ich sende kommt wieder zurück (und das funktioniert auch sicher).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1985756</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1985756</guid><dc:creator><![CDATA[Jacky2k]]></dc:creator><pubDate>Thu, 25 Nov 2010 17:28:32 GMT</pubDate></item><item><title><![CDATA[Reply to Socket nicht blockend lesen on Thu, 25 Nov 2010 18:55:01 GMT]]></title><description><![CDATA[<p>Ich glaube ich habe das Problem eben behoben. Ich verwende die cancel Methode nicht mehr, um read Vorgänge abzubrechen, statt dessen läuft nun immer ein Read Vorgang und startet sich dann quasi neu wenn er beendet wurde.</p>
<pre><code class="language-cpp">#ifndef BOOSTCOMPORT_HPP_
#define BOOSTCOMPORT_HPP_

#include &lt;boost/asio.hpp&gt;
#include &lt;string&gt;
#include &lt;iostream&gt;
#include &lt;boost/timer.hpp&gt;

#define BUFFER_SIZE 1000000

using namespace std;

class BoostComPort
{
public:
	BoostComPort();
	~BoostComPort();
	int open(std::string port, int baud);
	int close();
	bool isOpended();
	int write(char* Data, unsigned int Length);
	int read(char* data, int length, bool blocking=false, int timeout=-1 /* timeout in ms */);
	boost::system::error_code&amp; getLastError();

private:
	void onPortRead(const boost::system::error_code&amp; error, std::size_t bytes_transferred);

	char* buffer;
	int currentContent;
	bool executed;
	boost::asio::io_service io_service;
	boost::asio::serial_port serialPort;
	boost::system::error_code ec;
	boost::system::error_code lastError;
protected:

};

#endif
</code></pre>
<pre><code class="language-cpp">#include &quot;BoostComPort.hpp&quot;
#include &lt;boost/bind.hpp&gt;

BoostComPort::BoostComPort():
currentContent(0),
serialPort(io_service)
{
	lastError.clear();
	buffer=new char[BUFFER_SIZE];
}

BoostComPort::~BoostComPort()
{
	serialPort.close();
	delete[] buffer;
}

int BoostComPort::open(std::string port, int baud)
{
	if(serialPort.is_open())
		serialPort.close();
	serialPort.open(port);
	boost::asio::serial_port_base::baud_rate baudRate(baud);
	serialPort.set_option(baudRate);
	serialPort.async_read_some(boost::asio::buffer(buffer+currentContent, BUFFER_SIZE-currentContent), boost::bind(&amp;BoostComPort::onPortRead, this, _1, _2));
	char* tmp=new char[100]; // 5MBi of temporary buffer to clean the system buffers
	int read;
	do
	{
		read=this-&gt;read(tmp, 100, false);
	} while(read&gt;0);
	delete[] tmp;
	return 0;
}

boost::system::error_code&amp; BoostComPort::getLastError()
{
	return lastError;
}

int BoostComPort::close()
{
	serialPort.close();
	return 0;
}

bool BoostComPort::isOpended()
{
	return serialPort.is_open();
}

int BoostComPort::write(char* data, unsigned int length)
{
	size_t written=boost::asio::write(serialPort, boost::asio::buffer(data, length), boost::asio::transfer_all(), ec);
	if(written!=length)
		return -1;
	return 0;
}

int BoostComPort::read(char* data, int length, bool blocking, int timeout)
{
	boost::timer time;
	do
	{
		executed=false;
		io_service.poll(); // read new data
		if(executed)
			serialPort.async_read_some(boost::asio::buffer(buffer+currentContent, BUFFER_SIZE-currentContent), boost::bind(&amp;BoostComPort::onPortRead, this, _1, _2));
		if(timeout&gt;0)
		{
			if((int)(time.elapsed()*1000)&gt;timeout || !serialPort.is_open())
				return -1;
		}
	} while(blocking &amp;&amp; currentContent&lt;length);
	int toCopy;
	if(length&lt;currentContent)
		toCopy=length;
	else
		toCopy=currentContent;
	memcpy(data, buffer, toCopy);
	memcpy(buffer, buffer+toCopy, currentContent-toCopy);
	currentContent-=toCopy;
	return toCopy;
}

void BoostComPort::onPortRead(const boost::system::error_code&amp; error, std::size_t bytes_transferred)
{
	//cout&lt;&lt;&quot;BoostComPort::onPortRead(): called&quot;&lt;&lt;endl;
	if(error==0)
	{
		currentContent+=bytes_transferred;
		cout&lt;&lt;&quot;Read some bytes: &quot;&lt;&lt;bytes_transferred&lt;&lt;endl;
	}
	else if(error!=boost::asio::error::operation_aborted)  // not cancelled
	{
		cerr&lt;&lt;&quot;BoostComPort::onPortRead(): Unable to read from com port with error: &quot;&lt;&lt;endl;
		cerr&lt;&lt;&quot;BoostComPort::onPortRead():   Error message: &quot;&lt;&lt;error.message()&lt;&lt;endl;
		cerr&lt;&lt;&quot;BoostComPort::onPortRead():   Error code: &quot;&lt;&lt;error&lt;&lt;endl;
		lastError=ec;
	}
	executed=true;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1985804</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1985804</guid><dc:creator><![CDATA[Jacky2k]]></dc:creator><pubDate>Thu, 25 Nov 2010 18:55:01 GMT</pubDate></item></channel></rss>