2012-01-18 49 views
9

Estoy intentando implementar un programa cliente-servidor bidireccional, donde los clientes y servidores pueden pasar objetos serializados entre ellos. Estoy tratando de hacer esto usando Qt (QTcpSocket y QTcpServer). He implementado programas como este en Java, pero no puedo encontrar la manera de hacerlo usando Qt. He comprobado los ejemplos fortune client y fortune server ... pero por lo que puedo ver, el cliente simplemente está señalando el servidor y el servidor le envía algunos datos. Necesito que el cliente y el servidor envíen objetos de un lado a otro. No estoy buscando una solución completa, todo lo que busco es una guía en la dirección correcta.Servidor de cliente bidireccional Qt utilizando QTcpSocket y QTcpServer

Escribí un código que acepta una conexión, pero no acepta los datos.

SERVIDOR

esta clase es el servidor; debería aceptar una conexión y generar el tamaño del búfer que se está enviando. Sin embargo, está emitiendo 0

#include "comms.h" 

Comms::Comms(QString hostIP, quint16 hostPort) 
{ 
    server = new QTcpServer(this); 
    hostAddress.setAddress(hostIP); 
    this->hostPort = hostPort; 


} 

void Comms::attemptConnection(){ 
    connect(server, SIGNAL(newConnection()), this, SLOT(connectionAccepted())); 
    //socket = server->nextPendingConnection(); 
    server->listen(hostAddress,hostPort); 
    //receivedData = socket->readAll(); 
} 

void Comms::connectionAccepted(){ 
    qDebug()<<"Connected"; 
    socket = new QTcpSocket(server->nextPendingConnection()); 

    char* rec = new char[socket->readBufferSize()]; 
    qDebug()<<socket->readBufferSize(); 
} 

CLIENTE

Esta clase es el cliente. Debería estar enviando la cadena 'hola'. Se envía con éxito (que yo sepa)

#include "toplevelcomms.h" 
#include "stdio.h" 

TopLevelComms::TopLevelComms(QString hostIP, quint16 hostPort) 
{ 
    tcpSocket = new QTcpSocket(); 
    hostAddress.setAddress(hostIP); 
    this->hostPort = hostPort; 
} 


void TopLevelComms::connect(){ 
    tcpSocket->connectToHost(hostAddress,hostPort,QIODevice::ReadWrite); 
    //tcpSocket->waitForConnected(1); 

    QString string = "Hello"; 
    QByteArray array; 
    array.append(string); 
    qDebug()<<tcpSocket->write(array); 
} 

Por favor, dime lo que estoy haciendo mal, o me dice la lógica general de establecer lo que quiero en Qt.

Respuesta

9

QTcpSocket es asíncrona de forma predeterminada, por lo que cuando se llama a connectToHost y escribir en el mismo contexto que no habrá enviado, como socket no está conectado. Debe cambiar su "cliente" código:

void TopLevelComms::connect(){ 
    tcpSocket->connectToHost(hostAddress,hostPort,QIODevice::ReadWrite); 
    if(tcpSocket->waitForConnected()) // putting 1 as parameter isn't reasonable, using default 3000ms value 
    { 
     QString string = "Hello"; 
     QByteArray array; 
     array.append(string); 
     qDebug()<<tcpSocket->write(array); 
    } 
    else 
    { 
     qDebug() << "couldn't connect"; 
    } 
} 

Nota: también no comprobó si usted es capaz de escuchar

void Comms::attemptConnection(){ 
    connect(server, SIGNAL(newConnection()), this, SLOT(connectionAccepted())); 
    //socket = server->nextPendingConnection(); 

    if(server->listen(hostAddress,hostPort)) 
    { 
     qDebug() << "Server listening"; 
    } 
    else 
    { 
     qDebug() << "Couldn't listen to port" << server->serverPort() << ":" << server->errorString(); 
    } 
    //receivedData = socket->readAll(); 
} 

y lo último. Tenga en cuenta que QTcpServer :: nextPendingConnection() devuelven QTcpSocket, en lugar de que esa nueva conexión se crea nueva QTcpSocket con nextPendingConnection como padre

void Comms::connectionAccepted(){ 
    qDebug()<<"Connected"; 
    // WRONG! it will use QTcpSocket::QTcpSocket(QObject * parent) 
    //socket = new QTcpSocket(server->nextPendingConnection()); 
    // use simple asign 
    socket = server->nextPendingConnection(); 
    // move reading to slot 
    connect(socket, SIGNAL(readyRead()), this, SLOT(readSocket())); 
} 

ahora vamos a pasar a la lectura de ranura separada

void Comms::readSocket() 
{ 
    // note that dynamic size array is incompatible with some compilers 
    // we will use Qt data structure for that 
    //char* rec = new char[socket->readBufferSize()]; 
    qDebug()<<socket->readBufferSize(); 
    // note that QByteArray can be casted to char * and const char * 
    QByteArray data = socket->readAll(); 
} 

debo admitir, que es un montón de errores en cuanto a muestra de código tan pequeño. Necesita obtener algunos conocimientos sobre las conexiones TCP/IP. Esas son transmisiones y no hay garantía de que todo el fragmento de datos llegue a usted de inmediato

+1

Muchas gracias, pude enviar datos a través del socket.Sin embargo, sigo obteniendo un tamaño de buffer de 0 por alguna razón. ¿Alguna idea de por qué? – PTBG

+0

De los documentos "Un tamaño de almacenamiento intermedio de lectura de 0 (valor predeterminado) significa que el almacenamiento intermedio no tiene límite de tamaño, lo que garantiza que no se pierda ningún dato". Por lo tanto, no da ninguna indicación sobre el contenido real. Deberías usar 'socket-> size()' o 'socket-> bytesAvailable()' –

4

Parece que tiene un problema de tiempo. Dado que su cliente y su servidor son procesos diferentes, no hay forma de que pueda garantizar que la totalidad de TopLevelComms::connect() se esté ejecutando (junto con la transferencia de datos de red) antes de que la función connectionAccepted() del servidor intente leer desde el socket.

sospecho que si se toma ventaja de la función de QTcpSocket waitForReadyRead(), usted debe tener mejor suerte:

void Comms::connectionAccepted(){ 
    qDebug()<<"Connected"; 
    socket = new QTcpSocket(server->nextPendingConnection()); 

    if(socket->waitForReadyRead()) { 
     char* rec = new char[socket->readBufferSize()]; 
     qDebug()<<socket->readBufferSize(); 
    } 
} 
Cuestiones relacionadas