PDA

View Full Version : Socket not connecting



ComaWhite
4th March 2008, 20:46
I'm trying to connect to this server. The address is correct and the same with the port.



#include "MSNSocket.h"
using namespace ShadowMSN;

MSNSocket::MSNSocket(const QString& address, quint16 port, QObject* parent)
: QTcpSocket(parent),
m_address(address),
m_port(port)
{
connect(this, SIGNAL(readyRead()),
this, SLOT(receiveCommand()));
connect(this, SIGNAL(connected()),
this, SLOT(msnConnected()));
connect(this, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(errorHandling(QAbstractSocket::SocketError))) ;
connect(this, SIGNAL(stateChanged(QAbstractSocket::SocketState)) ,
this, SLOT(stateWasChanged(QAbstractSocket::SocketState) ));
m_socket = new QTcpSocket;
this->connectToHost(address, port);
}

QString MSNSocket::sendCommand(const QString& command)
{
if(command.isEmpty()) {
return " ";
}

m_msnCommand.parseCommand(command.toUtf8());
this->write(m_msnCommand.toString().toUtf8());
return m_msnCommand.toString().toUtf8();
}

void MSNSocket::receiveCommand()
{
//if(this->bytesAvailable())
//{
char* data = new char[this->bytesAvailable()];
qDebug() << this->read(data, this->bytesAvailable());
qDebug() << data;
//}
//else
//{
//qDebug() << "No data received";
//}
}

void MSNSocket::errorHandling(QAbstractSocket::SocketEr ror error)
{
qDebug() << "Error: " << error;
}

void MSNSocket::msnConnected()
{
qDebug() << "Connected";
}

void MSNSocket::stateWasChanged(QAbstractSocket::Socket State state){
qDebug() << "New State: " << state;
}




'./shadowmsn'
New State: QAbstractSocket::HostLookupState

wysota
4th March 2008, 23:24
Looks like your DNS can't find the address of the host.

ComaWhite
4th March 2008, 23:30
I had it where it was deleting the socket object before being processed. But now.
the socket is not working like I need for the communication to work with the server. It's sending all my commands first then it read the server's which is causing the connection to sever.

For example. I have to send like "me them me them" and what its doing is "me me them disconnect" I've tried reading the socket document but it's to no availble unless im over looking something.

wysota
5th March 2008, 05:07
You have to keep the state of the connection and react only when you receive a full response from the other side (in slot connected to readyRead()).

ComaWhite
7th March 2008, 04:24
I'm not sure that you mean?

wysota
7th March 2008, 07:52
You can't just write to the socket everything and then wait for answers for everything. You should only send another command when you receive answer to the previous one, and that's done in a slot connected to readyRead() signal. Refer to the docs for details.

ComaWhite
8th March 2008, 07:00
Okay i've rewrote my code to do like I wanted but it still wants to write one command after the other. Its forcing its self >.<

I've tried to use variable basing on it like m_canRead m_canWrite. doesn't help.




#include "MSNSocket.hpp"
namespace MSNP
{
MSNSocket::MSNSocket( QObject *parent )
: QObject( parent )
{
m_canWrite = true;
m_canRead = false;
m_connected = false;
m_blocksize = 0;
m_buffer.clear();

m_socket = new QTcpSocket;

QObject::connect( m_socket, SIGNAL( connected() ),
this, SLOT( msnConnected() ) );
QObject::connect( m_socket, SIGNAL( disconnected() ),
this, SLOT( msnDisconnected() ) );
QObject::connect( m_socket, SIGNAL( readyRead() ),
this, SLOT( receiveData() ) );
QObject::connect( m_socket, SIGNAL( error( QAbstractSocket::SocketError ) ),
this, SLOT( socketError( QAbstractSocket::SocketError ) ) );
QObject::connect( m_socket, SIGNAL( stateChanged( QAbstractSocket::SocketState ) ),
this, SLOT( stateWasChanged( QAbstractSocket::SocketState ) ) );
}

MSNSocket::~MSNSocket()
{
}

void MSNSocket::connect( const QString& address, const quint16 port )
{
if ( isConnected() ) {
return;
}

m_blocksize = 0;
m_buffer.clear();

m_socket->connectToHost( address, port );
}

void MSNSocket::disconnect()
{
if ( !isConnected() ) {
return;
}
m_socket->abort();
}

void MSNSocket::sendCommand( QString command, MSNSocket::CommandState state )
{
if ( !m_socket || !m_canWrite)
return;

m_msnCommand.parseCommand( command, true );
MSNLog::writeSend(m_msnCommand.toString());

m_socket->write( m_msnCommand.toString().toUtf8() );
m_canWrite = false;
m_canRead = true;
emit parseCommand( m_msnCommand );
}

void MSNSocket::readBlock( quint16 size )
{
if ( m_blocksize ) {
return;
}

m_blocksize = size;
checkBlock();
}

bool MSNSocket::isConnected()
{
return m_connected;
}

void MSNSocket::setConnected( bool status )
{
if ( m_connected == status ) {
return;
}

m_connected = status;
}

MSNCommand& MSNSocket::getLastCommand()
{
return m_msnCommand;
}

void MSNSocket::msnConnected()
{
m_connected = true;
emit connected();
}

void MSNSocket::msnDisconnected()
{
setConnected( false );
emit disconnected();
}

void MSNSocket::receiveData()
{
quint64 available = m_socket->bytesAvailable();
qDebug() << available;

char *buffer = new char[available + 1];
quint64 readBytes = m_socket->read( buffer, available );
m_canWrite = true;
m_canRead = false;
m_msnCommand.parseCommand( buffer, false );
MSNLog::writeReceive(m_msnCommand.toString());

if ( readBytes > 0 ) {
MSNLog::writeInfo( QString( "Bytes read returned %1" ).arg( readBytes ) );
} else if ( readBytes == 0 ) {
MSNLog::writeWarning( QString( "Bytes returned no data" ) );
} else {
if ( available ) {
if ( available != readBytes ) {
MSNLog::writeWarning(
QString( "Bytes read reported %1 bytes available but only read %2" ).arg( available ).arg( readBytes ) );
}
}

m_buffer.append( buffer );
}
// clean up.
delete []buffer;
}

bool MSNSocket::checkBlock()
{
if ( !m_blocksize ) {
return false;
} else if ( static_cast<quint64>( m_buffer.size() ) < m_blocksize ) {
MSNLog::writeInfo( QString( "Waiting for data %1. Received %2/%3" ).arg( m_buffer.size() ).arg( m_blocksize ) );
return true;
}

QByteArray block = m_buffer.take( m_blocksize );

m_blocksize = 0;
emit blockRead( block );
return false;
}
} // End of MSNP

wysota
8th March 2008, 08:04
The fact that you receive something doesn't yet mean you have received the whole command - you might have received a single byte. You should check that in the reading method.

Could you also show us how you use the above code in practice?

ComaWhite
8th March 2008, 08:09
#ifndef TEST_H
#define TEST_H

#include "MSNSocket.hpp"
#include "MSNCommand.hpp"
using namespace MSNP;

class Test : public MSNP::MSNSocket
{
Q_OBJECT
public:
Test(const QString& email, const QString& password, QObject *parent = NULL)
: MSNP::MSNSocket(parent)
{
m_email = email;
m_password = password;
QObject::connect(this, SIGNAL(connected()), this, SLOT(onConnection()));
QObject::connect(this, SIGNAL(blockRead(QByteArray&)), this, SLOT(receiveCommands(QByteArray&)));
QObject::connect(this, SIGNAL(parseCommand(MSNCommand&)), this, SLOT(parseCommands(MSNCommand&)));
connect("messenger.hotmail.com", 1863);
}
public slots:
void onConnection()
{
MSNLog::writeInfo( "Connected" );
sendCommand("VER MSNP15 MSNP14 CV0");
}

void parseCommands(MSNCommand& commands)
{
QString cmds = commands.getCommand();
if(cmds.contains("VER", Qt::CaseSensitive)) {
sendCommand("CVR 0x0409 unix gentoo i686 ShadowMSN 0.1 MSNSGS " + m_email);
}
if(cmds.contains("CVR", Qt::CaseSensitive)) {
sendCommand("USR TWN I " + m_email);
}
if(cmds.contains("XFR", Qt::CaseSensitive)) {
QStringList ip_port = commands.getParameters().split( " " );
QStringList ip_port_split = ip_port[1].split(":");

connect(ip_port_split[0], ip_port_split[1].toULong());
}
}

void receiveCommands(QByteArray& commands)
{
}
private:
QString m_email;
QString m_password;
};

#endif // TEST_H

wysota
8th March 2008, 08:20
Ok, and what exactly happens? What is being sent to the network?

ComaWhite
8th March 2008, 08:35
eckos@Narf ~/Samples $ ./samples
New State: QAbstractSocket::HostLookupState
New State: QAbstractSocket::ConnectingState
New State: QAbstractSocket::ConnectedState
[Info] "Connected"
[SEND] "VER 1 MSNP15 MSNP14 CV0
"
[SEND] "CVR 2 0x0409 unix gentoo i686 ShadowMSN 0.1 MSNSGS sample@live.com (xeckox@live.com)
"
[SEND] "USR 3 TWN I sample@live.com (xeckox@live.com)
"
149
[RECV] "VER 3 MSNP15 MSNP14
CVR 2 1.0.0000 1.0.0000 1.0.0000 http://msgr.dlservice.microsoft.com http://messenger.msn.com
XFR 3 NS 207.46.106.58:1863 U D

"
[Info] "Bytes read returned 149"
[ERROR] QAbstractSocket::RemoteHostClosedError
New State: QAbstractSocket::ClosingState
New State: QAbstractSocket::UnconnectedState
The socket specs requires a switch style commands being sent.
For example.
Send
Receive
Send
Receive.

wysota
8th March 2008, 08:41
Where is the code that triggers sending commands 2 and 3?

ComaWhite
8th March 2008, 08:49
In Test::parseCommands() sends the commands.
In MSNSocket sendCommand writes it to the socket.

wysota
8th March 2008, 09:07
I see now. When you send a command, you emit a signal that triggers sending the next command and here is your problem - all the commands are send practically at once without even checking if there is anything to be read from the socket. You should do it more or less like so:


enum State { Off, VerSent, CvrSent, Usr3Sent } state = Off;
...::onConnected() { sendCommand("Ver"); }
...::sendCommand(...) {
switch(state){
case Off: if(... == "Ver"){ socket.write(...); state = VerSent; }; break;
case VerSent: if(...){ socket.write(...); state = CvrSent; }; break;
...
}
}
::onReadyRead(){
if(!socket.canReadLine()) return;
switch(state){
case Off: /* shouldn't happen */ break;
case VerSent: sendCommand("CVR"); break;
case CvrSent: sendCommand("USR"); break;
default: /* regular traffic */
}
}

Sending command should be performed upon receiving response to a previous command, not upon sending the command as this way you'll send all commands at once without waiting for any response.

ComaWhite
11th March 2008, 02:55
Nevermind I finally got it working :D