4

ソケット インターフェイスに基づいて Raspberry PI 用のアプリを開発しています。主なアイデアは、Raspberry がセンサーに接続され、データを収集し、WiFi 経由で Android デバイスに送信することです。Android から、いくつかのコマンドを送信するセンサーと通信できます。私はこの種の開発の初心者であり、QTcpSocket に関するいくつかのチュートリアルに従って、単純なクライアント サーバー アプリを作成しましたが、それは一方向のみです。サーバーは、クライアントが何を送信しているかをリッスンします。双方向通信に改善するのを手伝ってくれませんか? QTcpSocket はこの種の問題に対してスレッド化を必要としないことを読みましたが、解決策が見つかりませんでした。

助けていただければ幸いです!

サーバー.cpp:

#include "server.h"
#include <QTcpServer>
#include <QTcpSocket>
#include <cstdio>
#include <QtDebug>

Server::Server(QObject *parent) :
QObject(parent)
{
    server = new QTcpServer(this);
    connect(server, SIGNAL(newConnection()),
    this, SLOT(on_newConnection()));
}

void Server::listen()
{
    server->listen(QHostAddress::Any, 5100);
}

void Server::on_newConnection()
{
    socket = server->nextPendingConnection();

    if(socket->state() == QTcpSocket::ConnectedState)
    {
        printf("New connection established.\n");
        qDebug()<<socket->peerAddress();
    }
    connect(socket, SIGNAL(disconnected()),
    this, SLOT(on_disconnected()));
    connect(socket, SIGNAL(readyRead()),
    this, SLOT(on_readyRead()));
}

void Server::on_readyRead()
{
    while(socket->canReadLine())
    {
        QByteArray ba = socket->readLine();

        if(strcmp(ba.constData(), "!exit\n") == 0)
        {
            socket->disconnectFromHost();
            break;
        }
        printf(">> %s", ba.constData());
    }
}

void Server::on_disconnected()
{
    printf("Connection disconnected.\n");
    disconnect(socket, SIGNAL(disconnected()));
    disconnect(socket, SIGNAL(readyRead()));
    socket->deleteLater();
}

client.cpp

#include "client.h"
#include <QTcpSocket>
#include <QHostAddress>
#include <cstdio>

Client::Client(QObject *parent) : QObject(parent)
{
    socket = new QTcpSocket(this);
    printf("try to connect.\n");
    connect(socket, SIGNAL(connected()),
    this, SLOT(on_connected()));
}

void Client::on_connected()
{
    printf("Connection established.\n");
    char buffer[1024];
    forever
    {
        while(socket->canReadLine())
        {
            QByteArray ba = socket->readLine();
            printf("from server: %s", ba.constData());
        }
        printf(">> ");
        gets(buffer);
        int len = strlen(buffer);
        buffer[len] = '\n';
        buffer[len+1] = '\0';
        socket->write(buffer);
        socket->flush();
    }

}

void Client::connectToServer()
{
    socket->connectToHost(QHostAddress::LocalHost, 5100);
}
4

2 に答える 2

6

アーキテクチャの観点から、最初にサーバーとクライアント間の通信ルール (メッセージ フロー) を定義する必要があります。

次に、定義されたフローに従って、QTCPSocket のインスタンスから (から) 読み取り (書き込み) を行うだけです。

たとえば、サーバー側でデータを読み取り、何に答える必要があるかを確認し、読み取り元と同じソケットに応答を書き込むことができます。行指向のメッセージ (およびそれらのみ) の場合、コードは次のようになります。

    void Server::on_readyRead()
    {
        // "while" loop would block until at least one whole line arrived
        // I would use "if" instead
        if(socket->canReadLine()) 
        {
            QByteArray ba = socket->readLine();

            QByteArray response;

            // some code which parses arrived message
            // and prepares response

            socket->write(response);
        }
        //else just wait for more data
    }

個人的には、on_readyRead() スロットからの応答の送信と解析を移動して、イベント ループが長時間ブロックされないようにしますが、ネットワーク プログラミングの初心者なので、双方向通信を実装するために何ができるかを明確にしたかっただけです。

詳細については、 http: //qt-project.org/doc/qt-4.8/qtnetwork.htmlを参照してください。

クライアント側とサーバー側の両方でメッセージ全体が到着したかどうかを確認することを忘れないでください。独自のプロトコル (HTTP、FTP、その他の標準化されていない) を使用する場合は、メッセージの先頭にメッセージの長さを追加できます。

于 2013-06-17T15:01:10.230 に答える
1

クライアントまたはサーバーからソケットに書き込み/読み取りを行うだけです。TCP 接続はすでに双方向接続です。

foreverのループに問題がある可能性がありますClientreadyReadサーバーに対して行うのと同じ方法でソケットでシグナルを実際に使用し、そのforeverループをドロップする必要があります。

を使用するのではなく、ブロックしない方法でキーボード入力を処理しgets()ます。 gets()メイン スレッドをブロックし、イベント ループの実行を防ぎます。サーバーからのデータとユーザーからのデータを同時に処理できるようにする必要があるため、これはあなたのケースで物事を処理するための最良の方法ではありません。

コンソールアプリからのキーボード処理に関して、これを見てください:

非ブロッキング方式で qtextstream-to-read-stdin を使用

または、GUI アプリにして、QPlainTextEdit.

于 2013-06-17T12:55:25.217 に答える