2012-01-18 1 views
9

클라이언트와 서버가 서로간에 직렬화 된 객체를 전달할 수있는 양방향 클라이언트 - 서버 프로그램을 구현하려고합니다. Qt (QTcpSocket 및 QTcpServer)를 사용하여이 작업을 수행하려고합니다. 나는 java와 같은 프로그램을 구현했지만 Qt를 사용하여이를 수행하는 방법을 알 수 없다. fortune clientfortune server 예제를 확인했지만, 내가 볼 수있는 것부터 클라이언트는 단순히 서버에 신호를 보내고 서버가 데이터를 전송합니다. 클라이언트와 서버가 객체를주고받을 필요가 있습니다. 나는 완전한 해결책을 찾지 않고 있으며, 내가 바라는 것은 올바른 방향으로 인도하는 것이다.QTcpSocket 및 QTcpServer를 사용하는 Qt 양방향 클라이언트 서버

연결을 허용하지만 데이터를 허용하지 않는 코드를 작성했습니다.

서버에

이 클래스는 서버입니다; 그것은 연결을 받아 들여 보내고있는 버퍼의 크기를 출력해야합니다. 그러나 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(); 
} 

CLIENT

이 클래스를 출력하는 것은 클라이언트입니다. 'hello'문자열을 보내야합니다. 그것은

#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); 
} 

내가 잘못 뭘하는지 말해, 또는 나에게 내가 Qt를에서 원하는 설정의 일반적인 논리를 알려주세요 (내 지식) 성공적으로 전송한다.

답변

9

QTcpSocket는 기본적으로 비동기, 그래서 당신이 connectToHost 전화와 같은 맥락에서 쓸 때이되지 않습니다 소켓이 연결되지 않았으므로 보냈습니다.

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"; 
    } 
} 

주 : 당신은 당신의 "클라이언트"코드를 변경해야합니다 당신이

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(); 
} 

그리고 마지막을들을 수 있다면 당신은 또한 확인하지 않았다. QTcpServer :: nextPendingConnection은() 그래서 대신에 새 연결 우리가 별도의 슬롯

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(); 
} 

내가해야에게 책을 읽어 이동합니다 지금

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())); 
} 

부모 nextPendingConnection 새로운 QTcpSocket을 만드는 것이 복용, QTcpSocket을 반환합니다 그러한 작은 코드 샘플에 대해서는 많은 오류가 있음을 인정합니다. TCP/IP 연결에 대한 지식이 필요합니다. 그것들은 스트림이고, 전체 데이터 덩어리가 당신에게 즉시 도착할 것이라는 보증은 없습니다.

+1

대단히 감사합니다. 소켓을 통해 데이터를 보낼 수있었습니다.그러나 나는 아직도 어떤 이유로 0의 버퍼 크기를 얻고있다. 왜 그런가? – PTBG

+0

docs에서 "0 (기본값)의 읽기 버퍼 크기는 버퍼에 크기 제한이 없으므로 손실 된 데이터가 없음을 의미합니다." 따라서 실제 내용에는 아무런 변화가 없습니다. 당신은'socket-> size()'또는'socket-> bytesAvailable()'을 사용해야합니다. –

4

타이밍 문제가있는 것으로 보입니다. 클라이언트와 서버가 서로 다른 프로세스이기 때문에 서버의 connectionAccepted() 함수가 소켓에서 읽기를 시도하기 전에 TopLevelComms::connect()의 전체가 (네트워크 데이터 전송과 함께) 실행되고 있음을 보장 할 수있는 방법이 없습니다.

난 당신이 QTcpSocket의 waitForReadyRead() 기능을 활용하면, 당신은 더 나은 운이해야한다고 생각 :

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

    if(socket->waitForReadyRead()) { 
     char* rec = new char[socket->readBufferSize()]; 
     qDebug()<<socket->readBufferSize(); 
    } 
} 
관련 문제