(gelöst) QTcpSocket Datenübertragung endet bei 65532 byte

Alles rund um die Programmierung mit Qt
Antworten
Ritchie
Beiträge: 86
Registriert: 29. Januar 2007 19:41

(gelöst) QTcpSocket Datenübertragung endet bei 65532 byte

Beitrag von Ritchie »

Hallo Zusammen,

ich versuche derzeit eine Datenklasse via QDataStream über TCP/IP zu übertragen.
Das ganze hat bis eine Datenmenge von 65000 bis jetzt immer prima geklappt. Da meine Datenmenge
jetzt größer wurde, habe ich auf "qint32 Datenlänge erweitert."


Hier die Stream Operatoren dafür den *Pointer der verwendeten Klasse

Code: Alles auswählen

// *************************************************************
//			Stream out operator
// *************************************************************

QDataStream& operator<<(QDataStream& stream, const DataBlock& data)
{
qint32				bytesToSend;
int						BlockSize;
int						BytesWritten=1;
char					*pointer;


	stream	<< data.getStorageTime() 
					<< data.getDescription()
					<< data.getSize()
					<< data.getUsedSize()
					<< data.getNumber()
					<< data.getSubNode()
					<< (int) data.getType()
					<< data.getQuality()
					<< data.getCheckSum()
					<< data.getCycleReadTime();

	bytesToSend = data.getSize();
	if( bytesToSend > 32760)
		BlockSize=32760;
	else
		BlockSize=(int) bytesToSend;

	pointer=data.getData();
	while (bytesToSend > 0 && BytesWritten > 0)
		{	
		BytesWritten=stream.writeRawData( pointer , BlockSize) ;
		if(  BytesWritten > 0 )
			{
			bytesToSend -= BytesWritten;
			if( bytesToSend > 0 )
				{
				pointer +=BytesWritten;
				if( bytesToSend > 32760)
					BlockSize=32760;
				else
					BlockSize=(int) bytesToSend;
				}
			}
		}

	return stream;
}

// *************************************************************
//			Stream in operator
// *************************************************************

QDataStream& operator>>(QDataStream& stream,DataBlock& data)
{
QDateTime		Temp1;
QString				Temp2;
int						iTemp1;
int						iTemp2;
int						iTemp3;
qint32				UsedSize;
qint32				bytesToReceive=1;
int						BlockSize;
int						BytesReceived=1;
char					*pointer;


	stream >> Temp1 >> Temp2 >> bytesToReceive  >> UsedSize >> iTemp1 >> iTemp2 >> iTemp3;
	data.setStorageTime(Temp1);
	data.setDescription(Temp2);
	data.setSize(bytesToReceive);
	data.setUsedSize(UsedSize);
	data.setNumber(iTemp1);
	data.setSubNode( iTemp2);
	data.setType( (BlockDataType)iTemp3);

	stream >> iTemp1  >> iTemp2 >> iTemp3;
	data.setQuality(iTemp1);
	data.setCheckSum( iTemp2 );
	data.setCycleReadTime( iTemp3 );

	if( bytesToReceive > 32760)
		BlockSize=32760;
	else
		BlockSize=(int) bytesToReceive;

	pointer=data.getData();
	while (bytesToReceive > 0 && BytesReceived > 0 )
		{	
		BytesReceived=stream.readRawData(pointer, BlockSize);
		if( BytesReceived > 0)	
			{
			pointer +=BytesReceived;
			bytesToReceive -= BytesReceived;
			if( bytesToReceive > 0 )
				{
				if( bytesToReceive > 32760)
					BlockSize=32760;
				else
					BlockSize=(int) bytesToReceive;
				}
			}
		}

	return stream;
}
Hier der Sende Teil (vereinfacht, nur der Teil des Writes in den Socket:

Code: Alles auswählen

         out << *Pointer;	
         out << m_AccessPoint->getStatus();
         LockPointer->unlock();

	out.device()->seek(0);																			// jump back to the start of the block
	out << (quint32)(m_block.size() - sizeof(quint32));			// write the size of data - size info into	
	Socket->write(m_block);																		// Send data to the Client
	Socket->waitForBytesWritten(5000);

Hier der Empfangsteil:

( tcpSocket->bytesAvailable() ) gibt mir für den Datenteil immer nur 65532 als Max. verfügbare Daten.

Code: Alles auswählen

			QDataStream in(tcpSocket);													// Create a data stream by tcp/ip
			in.setVersion(QDataStream::Qt_4_5);									// we are using version 4.5
			in >> blockSize;	
			while ( tcpSocket->bytesAvailable() < blockSize )
				{
				if ( tcpSocket->waitForReadyRead(65000) == false) 
					{
					m_ActualAccess->setStatus(false);								// Failure communication
					m_LockPointer->unlock();												// Release lock of data block for other
					delete		tcpSocket;															// Clean up the socket
					return;																					// abort function 
					}
				}
			in >>  *m_Pointer;																		// Get the object into the buffer
			in >> UnitState;																			// get the state of the PLC
			tcpSocket->disconnectFromHost();										// disconnect connection
			m_ActualAccess->setStatus(UnitState);								// Set the access point state
hier noch die vereinfachte Empfangsroutine:

Code: Alles auswählen

quint32						blockSize;	

QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_5);	
in >> blockSize;	
while ( tcpSocket->bytesAvailable() < blockSize )
	{
	if ( tcpSocket->waitForReadyRead(65000) == false) 
	   {
           return;
           }
        }
in >>  *m_Pointer;
in >> UnitState;
tcpSocket->disconnectFromHost();
Hat jemand eine Idee, was ich falsch mache oder noch fehlt ?

Gruss R.
Zuletzt geändert von Ritchie am 2. Januar 2012 19:18, insgesamt 2-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QTcpSocket Datenübertragung endet bei 65532 byte

Beitrag von Christian81 »

Deine Senderoutine ist verwirrend - auf der einen Seite schreibst Du was nach out (was wohl ein QDataStream ist?), auf der anderen Seite direkt in ein QTcpSocket. Und wenn out wirklich ein TcpSocket ist dann wird seek() definitiv nicht funktionieren. Ein funktionierendes Testcase in dem man sieht was da wirklich passiert wäre schon nicht schlecht...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ritchie
Beiträge: 86
Registriert: 29. Januar 2007 19:41

Re: QTcpSocket Datenübertragung endet bei 65532 byte

Beitrag von Ritchie »

Hallo,

sorry. War vielleicht falsch dargestellt. Ich versuche es nochmal.

Vom Prinzip her ist es eigentlich ein "in" und "out", welcher über ein Socket gesendet wird.
Ich verwende hierbei die QDataStream Klasse und in meiner Klasse habe ich die Operatoren << und >> dafür eingebaut.

Der Ärger hat damit angefangen, das ich eine Datenmenge von über 100kByte habe, welcher
sich nicht mehr mit "readRawData"/ "writeRawData" von QDataStream in einem Rutsch senden läßt.

Die Datenmenge der zu sendenden Byte ist hier auf "int" beschränkt.
Daher habe ich die Datenmenge in einzelne Blocke aufgeteilt:

Siehe hier den Codeausschnitt aus dem oberen Operatorausschnitt:

Code: Alles auswählen

	if( bytesToReceive > 32760)
		BlockSize=32760;
	else
		BlockSize=(int) bytesToReceive;

	pointer=data.getData();
	while (bytesToReceive > 0 && BytesReceived > 0 )
		{	
		BytesReceived=stream.readRawData(pointer, BlockSize);
		if( BytesReceived > 0)	
			{
			pointer +=BytesReceived;
			bytesToReceive -= BytesReceived;
			if( bytesToReceive > 0 )
				{
				if( bytesToReceive > 32760)
					BlockSize=32760;
				else
					BlockSize=(int) bytesToReceive;
				}
			}
		}
Eigentlich wird jetzt ein Stream via "QDataStream" geöffnet und dieser über einen QTcpSocket versendet.
Der seek ist noch in dem QDataStream Objekt und sollte eigentlich noch gehen. Die korrekte Datenmenge kommt auch auf der Partnerseite an.

Code: Alles auswählen

QByteArray 	m_block;

QDataStream		out(&m_block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_5);
out << (quint32)0;
out << *Pointer;	
out.device()->seek(0);	
out << (quint32)(m_block.size() - sizeof(quint32));
Socket->write(m_block);
Socket->waitForBytesWritten(5000);
sollte dann eigentlich die gesamte Klasse via dem Operator übertragen.

Nur bleibt auf der Partnerseite die Übertragung bei 65532 stehen, obwohl die Datenmenge bei ca. 92000 liegt.


Gruss R.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QTcpSocket Datenübertragung endet bei 65532 byte

Beitrag von Christian81 »

Was soll das mit der BlockSize? Hast Du da evtl. einen Fehler drin? Warum ist das überhaupt nötig ein Integer geht bis 2^31 - 2GB sollten doch wohl reichen, oder?
Beim Rest sehe ich nicht wirklich ein Problem - wie gesagt - das kann man eigentlich recht gut auf ein sehr kleines Testcase herunterbrechen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ritchie
Beiträge: 86
Registriert: 29. Januar 2007 19:41

Re: QTcpSocket Datenübertragung endet bei 65532 byte

Beitrag von Ritchie »

Hi,

die Variable "BlockSize" habe ich eingeführt, weil die Deklaration von

http://doc.trolltech.com/4.7/qdatastrea ... iteRawData

Code: Alles auswählen

int QDataStream::writeRawData ( const char * s, int len )
Und die Datenübertragung scheint bei mir bei genau int (0-65535) zu Ende.

Sehe ich das mit "int" hier falsch ? Ansonsten verwendet QT ja immer korrekte Datenbreite in der Beschreibung "qint8"...qint32"

Wenn ja, dann brauche ich den ganzen Aufwand ja nicht zu treiben mit dem splitten der Pakete.

Edit: Zusatz.
Die Senderoutine meldet 92160 Bytes gesendet und die Routine tcpSocket->bytesAvailable() meldet immer 65532 Bytes. Egal ob ich die Daten splitte oder im ganzen sende. :-(

Ich verwende übrigens kUbuntu 11.10 als OS.



Gruss R.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: QTcpSocket Datenübertragung endet bei 65532 byte

Beitrag von Christian81 »

Wie ich schon sagte - in hat nichts mit 65535 zu tun. Ein int ist immer 4 Byte breit, geht also bis 2^31 - 1 ...
Vielleicht ist der Rest noch in anderen Puffern - lies doch erstmal die Daten aus und warte auf neue - so mache ich es eigentlich immer. Wenn keine Daten mehr da sind dann muss man auf das nächste readyRead() warten.
Auf der Sendeseite würde ich noch ein flush() einbauen damit auch wirklich sichergestellt ist dass die Daten auch verschickt wurden - siehe QTcpSocket::flush(). Ansonsten sind die Daten ggf.noch in irgendwelchen Buffern (von Qt oder vom System) - denn die Sockets sind asynchron!
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Ritchie
Beiträge: 86
Registriert: 29. Januar 2007 19:41

Re: QTcpSocket Datenübertragung endet bei 65532 byte

Beitrag von Ritchie »

Hallo,

nachdem ich

Code: Alles auswählen

	out.setVersion(QDataStream::Qt_4_5);
auf

Code: Alles auswählen

	out.setVersion(QDataStream::Qt_4_6);
geändert habe, hat das ganze auch korrekt gearbeitet.

Gruss R.
Antworten