【问题标题】:QTcpServer with android client unable to print or use data received from client带有android客户端的QTcpServer无法打印或使用从客户端接收到的数据
【发布时间】:2015-05-26 18:59:38
【问题描述】:

我正在使用 Qt 框架在 C++ 中开发客户端-服务器应用程序,但客户端可以是 android 手机和计算机(Qt 客户端应用程序) 现在我在处理服务器端的数据接收时遇到了麻烦;服务器没有正确接收数据。

首先,我使用以下方法在服务器(Qt 应用程序)和客户端(Qt 应用程序)之间进行了良好的发送和接收: 消息的大小保留在数据包的开头,以帮助检查是否收到了整个消息。

这是向客户端发送消息的方法

void Server::send(const QString &message)
{
    QByteArray paquet;
    QDataStream out(&paquet, QIODevice::WriteOnly);

    out << (quint16) 0; // just put 0 at the head of the paquet to reserve place to put the size of the message
    out << message; // adding the message
    out.device()->seek(0); // coming back to the head of the paquet
    out << (quint16) (paquet.size() - sizeof(quint16)); // replace the 0 value by the real size


    clientSocket->write(paquet); //sending...

}

每次收到一个包时都会调用这个槽。

void Server::dataReceived()
{
    forever 
    {
        // 1 : a packet has arrived from any client

        // getting the socket of that client (recherche du QTcpSocket du client)
        QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
        if (socket == 0) 
            return; 

        QDataStream in(socket);

        if (dataSize == 0) // if we don't know the size of data we are suppose to receive...
        {
            if (socket->bytesAvailable() < (int)sizeof(quint16)) // we haven't yet receive the size of the data completly then return...
                 return;

            in >> dataSize; // now we know the amount of data we should get
        }

        if (socket->bytesAvailable() < dataSize) 
            return;

        // Here we are sure we got the whole data then we can startreadind
        QString message;
        in >> message;

        //Processing....

        dataSize = 0; // re-initialize for the coming data
    }
}

这在服务器与 Qt 应用程序客户端对话时运行良好,因为在那里使用相同的方法,并且 quint16 的大小将保持相同悬停它不适用于 android 客户端,然后我尝试了另一种方法在其中我想忽略发送的消息的大小,但是以某种方式格式化消息,以便我可以知道它从哪里开始和在哪里结束,然后通过一些控件我可以得到它但是我被困在这里,导致打印时读取的数据不包含任何内容,但他的大小有一个值(甚至根据客户端发送的文本量而变化)!

void Server::dataReceived() // a packet is received!
{

    QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
    if (socket == 0)
        return;


    QByteArray data= socket->readAll(); //reading all data available
    QString message(data)

    qDebug() << data;        // this prints nothing!
    qDebug() << data.size();//  But this prints a non null number, wich means we got something, and that number varies according to the amount of text sent!
    qDebug() << message;    // this also prints notghing!

} 

PS:即使是 Qt 应用客户端也无法正常工作。

你能帮我找出问题所在吗,我有点困惑 tcp 协议是如何处理数据的,如果你可以的话,也可以告诉我一个这样做的好方法。

这是我为此目的制作的 android 类

class QTcpSocket implements Runnable {

    private String ip="";
    private int port;
    private Socket socket;
    private PrintWriter printWriter;

    private DataOutputStream dataOutputStream;
    private DataInputStream dataInputStream;

    public QTcpSocket(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

      public void setIp(String ip) {
          this.ip = ip;
      }

      public String getIp() {
          return this.ip;
      }

    public void setPort(int port) {
        this.port = port;
    }

    public void run() {
        try {
            socket = new Socket(this.ip, this.port);
            dataOutputStream = new DataOutputStream( socket.getOutputStream() );
            dataInputStream = new DataInputStream(socket.getInputStream());
            String response = dataInputStream.readUTF();
            dataOutputStream.writeUTF("Hello server!");


        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void sendMessage(String message) {
        try {

            dataOutputStream.writeUTF(message);
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void disconnect() {
        try {

            printWriter.flush();
            printWriter.close();
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isClosed() {
        return socket.isClosed();
    }
}

【问题讨论】:

  • 你不应该创建一个新的 dataReceived() 而是让你的 android 客户端先发送消息的大小。请再试一次。不要使用 writeUTF 而是写入。请说明您为什么断定它无法与 android 客户端一起使用。
  • sendMessage。我没有看到在android代码中使用。
  • // But this prints a number, wich means we got somthing。 0?当然,最好说出数字是多少。
  • sizeof(quint16) 多少钱? 2?
  • Google for 'c++ write byte as hex'。作为替代方法,将“数据”中所有值为 0 的字节替换为值 20 并再次打印。我认为您没有看到任何打印内容,因为第一个字节是 0。您也可以替换为“X”。

标签: android qt tcp qtcpsocket qtcpserver


【解决方案1】:

用值 20 替换 'data' 中所有值为 0 的字节并再次打印。我认为您没有看到任何打印内容,因为第一个字节是 0。您也可以替换为“X”。您是否已经将 writeUTF() 替换为 write() ?

20 是空格字符。但是您也看不到任何打印内容,因此最好使用 X 字符。字符串被打印,直到遇到 \0 字符(表示字符串的结尾)。因为没有打印任何东西,所以我一开始就认为是正确的。所以 writeUTF 会导致前导 0。我只能解释如果所有字符都翻了一番。您发送的第一个字符是什么?

但是现在:首先发送消息大小,使其等于您的 qt 客户端。

【讨论】:

  • 是的,它与 write() 一起工作得更好,我替换了。不是32个空格字符吗?来自 ASCII 表的 AFAIK。为了首先发送消息的大小,我使用 quint16 而不是 int,因为它的 sizeof() 不会从一个系统更改为另一个系统,我不确定 java,因为如果更改,应用程序将失败
  • 您最好立即使用 quint32,否则您无法传输正常尺寸的图像。哈哈 0x20==32。
  • 我想是的。如果我使用 long 它应该可以工作,因为 Java 中的 long 需要 8 个字节并且 sizeof(quint64) = 8
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-24
  • 2013-12-04
  • 1970-01-01
  • 1970-01-01
  • 2014-08-29
  • 2010-09-25
  • 2021-09-30
相关资源
最近更新 更多