PDA

View Full Version : Why port switching unexpected after established tcp-socket connection in certain case



Klaus_EAN
13th April 2007, 10:27
Hello to all,

I have registered here, because I have serious problems with tcpsocket-connections. Maybe someone knows how to solve my problems.
And yes, I have searched in the database here before posting this.

Problem description:
Transfering data from a client (in the same subnet) to the server causes a port-switching between the
first syn-flag and the later communication. This is not seen, if client runs on the same box as the server.
At least data will be "lost" (resp. not "catched") on the server side, if client is not local and data to be transfered is bigger (appr. 65KB).

Situation:
Operating system is Ubuntu 6.xx, compilation with qmake/make for Qt4-stuff
A Qt-client makes a connection to a server, which is implemented in C/C++ (can't use Qt!!)
The client is fully designed/coded with Qt4 designer and QTcpSocket-stuff.
The instantiation of the socket-object is done dynamically with the "new" operator (client).

The steps on client side to communicate:

tcpSocket = new QTcpSocket(this);
tcpSocket->connectToHost(thehostip, spinBox_port->value());
tcpSocket->waitForConnected(1000))
qint64 byteswritten = tcpSocket->write(thedata);
tcpSocket->waitForBytesWritten();

After this, an "additionally" check on client was done, that the whole amount of the file, which has been read to send, was really sent.


I tried this to achive the goal:
On server side "tcpdump" watches the networktraffic (filter all syn- and fin-flags with 'tcp[13] & 3 !=0').
If client is on the s a m e box you can see the following sequence:
Syn, Syn, Fin, Fin on the same port (negotiated after the first contact, initial port is 5555, then e.g. 37690).
If client is on a different machine but in the same subnet you can see the following sequence:
Syn, Syn, port switching +1 Syn (new port),Syn (new port), Fin (new port), Fin (new port)
Sometimes the second Fin is NOT seen, if file is big (tested with appr. 64200 bytes).

Using the "swiss knife" netcat on client side (same subnet) with the big file, there is NO portswitching (nc 192.168.100.71 5555 < big_file).

On server side the following code snippets are used to establish a "listen" and "accept" (BSD-sockets!)


(/* C/C++ */)
TCPSocket * theSock = new TCPSocket ();
int ret = theSock->Bind(host, port); //bind and listen combined!

TCPSocket * theNewSocket = theSock->Accept(); // this is done in a loop forever
int NumberBytesRead = theNewSocket->Read(theBuffer, BUFFER_SIZE);

ioctl(theNewSocket->sock, FIONREAD, &rlen); //watching, if there is (fragmented)data on the socket not read yet

while (rlen > 0)
{
int NumberBytesRead = theNewSocket->Read(theBuffer, rlen);
.... Handle_theBuffer...

ioctl(theNewSocket->sock, FIONREAD, &rlen);//update register, maybe more to read?
}


Thanks for reading my post till here.
I would be happy to give more information, if needed.


Thanks again, hoping for an answer.

With best regards

Klaus

wysota
13th April 2007, 11:36
What exactly do you mean by "port switching"? Who changes the port? The client or the server? Could it be that there is some routing involved that causes the port change? I understand that the server side is not Qt based, correct?

Klaus_EAN
13th April 2007, 12:05
Hi wysota,

thanks for your reply.
The Qt-client changes the port as you can see in the following (shorten) tcpdump sequence (S= syn flag set, F= fin flag set, 45125 is in this example the port no. after accept):

192.168.100.112.45125 -> server S
server -> .112.45125 S
.112.45126 -> server S //here is the port change!!!
server -> .112.45126 S

server -> .112.45126 F
.112.45126 -> server F

To your questions:
The server and the Qt-client are connected with a crossover-cable.
The server is not Qt based, correct.

Greetings
Klaus

wysota
13th April 2007, 12:37
Could you verify that the client only calls connectToHost() once? Does the client use a separate thread for tcp communication? If not, maybe you should rely on signals instead?

Klaus_EAN
13th April 2007, 13:24
wysota,

connectToHost() is called only once, I have checked this again in the sources. mhh, why should it work on the SAME machine without double-call, if there are double entries for connect()?
I dont use multi-threads, in fact I could call exit(), if data is sent to the server.
I use Signals and slots as following (for reading a file and send it via tcp):



connect(getFilenameToReadButton, SIGNAL(clicked()), this, SLOT(getFilenameToRead()));
connect(this, SIGNAL(getFilenameToRead(const QString&)), this, SLOT(readFile(const QString&)));
connect(this, SIGNAL(readFile(const QByteArray&)), this, SLOT(sendviaTCP(const QByteArray&)));


in sendviaTCP(....) the needed code is straight forward to do connect/wait for connect/write/wait for bytes written.

Other ideas?

regards
Klaus

wysota
13th April 2007, 14:05
connectToHost() is called only once, I have checked this again in the sources.
This is not enough, check runtime :)


mhh, why should it work on the SAME machine without double-call, if there are double entries for connect()?
The problem could be time/latency related.


I dont use multi-threads, in fact I could call exit(), if data is sent to the server.
I use Signals and slots as following (for reading a file and send it via tcp):



connect(getFilenameToReadButton, SIGNAL(clicked()), this, SLOT(getFilenameToRead()));
connect(this, SIGNAL(getFilenameToRead(const QString&)), this, SLOT(readFile(const QString&)));
connect(this, SIGNAL(readFile(const QByteArray&)), this, SLOT(sendviaTCP(const QByteArray&)));


in sendviaTCP(....) the needed code is straight forward to do connect/wait for connect/write/wait for bytes written.

Try making use of these signals instead of using waitFor* methods:

void QAbstractSocket::connected ()
void QAbstractSocket::disconnected ()
void QIODevice::bytesWritten ( qint64 bytes )
void QIODevice::readyRead ()

Klaus_EAN
18th April 2007, 15:04
Hi wysota,

sorry for the delay.
This was caused due to finding out why a port change appears.
I got it :-)

I have coded some testclients with pure C, Qt with signals/slots as your proposal.
Pure C and Qt with signal/slots do NOT change the port so far.
Then I got a strange idea to put a sleep into my application between socket->connectToHost(...) and socket-waitForConnected(..).
The behaviour locally is not different (only the small delay), but on the remote machine executed, I can't see a port change anymore.

So far I have to investigate a little bit more..

t.b.c

thanks

Klaus