【问题标题】:QT - JAVA socket loss dataQT - JAVA 套接字丢失数据
【发布时间】:2015-01-28 00:40:19
【问题描述】:

我有一个 QT/C++ 服务器和一个 Java 客户端。 客户端向服务器请求文件,服务器将流发送给客户端。 问题是在 TCP 传输中(也在 localhost 中)我丢失了一些数据包。 有时,客户端会收到 288890 的 280705 个字节。

有服务器:

MyTcpServer::MyTcpServer(QObject *parent) :
    QTcpServer(parent)
{
}

void MyTcpServer::startServer(int port)
{
    if(!this->listen(QHostAddress::Any, serverPort))
    {
        qDebug() << "Could not start server";
    }
    else
    {
        qDebug() << "Listening to port " << serverPort << "...";
    }
}

void MyTcpServer::incomingConnection(qintptr socketDescriptor)
{
    SocketThread *thread = new SocketThread(socketDescriptor, this);
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
}

这是 SocketThread:

SocketThread::SocketThread(qintptr ID, QObject *parent) :
QThread(parent)
{
    this->socketDescriptor = ID;
}

void SocketThread::run()
{
    socket = new QTcpSocket();
    if(!socket->setSocketDescriptor(this->socketDescriptor))
    {
        emit error(socket->error());
        return;
    }
    connect(socket, SIGNAL(readyRead()),    this, SLOT(readyRead()), Qt::DirectConnection);
    connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));

    socket->write("Welcome to the Server\r\n"); //SEND AN HELLO MESSAGE
    socket->waitForBytesWritten();
    exec();
}

void SocketThread::readyRead()
{       
    QByteArray socketByteArray = socket->readAll();

    int number = 0;
    QDataStream socketDataStream(socketByteArray);
    socketDataStream >> number; //RECEIVE A NUMBER (I WANT 1)
    if (number == 1)
    {
       QFile file("C:\\temp\\test.txt");
       file.open(QIODevice::ReadWrite);

        socket->write(QString("%1\n").arg(file.size()).toStdString().c_str()); //SEND THE FILESIZE AS STRING
        socket->waitForBytesWritten();
        QByteArray buffer = file.readAll();
        long byteSent = socket->write(buffer); //SEND THE FILE

        socket->flush();
        file.close();
    }
    socket->close();
}

void SocketThread::disconnected()
{
    socket->deleteLater();
    exit(0);
}

这是 JAVA 客户端:

Socket MyClient = null;

boolean connect()
{
  try
  {
    MyClient = new Socket(remoteIP, remotePort);
    MyClient.setSoTimeout(60000);
    if (MyClient != null) {
        inFromServer = new BufferedReader(new InputStreamReader(MyClient.getInputStream()));

        serverWelcomeMessage = inFromServer.readLine(); //RECEIVE THE WELCOME MESSAGE
    }
  }
  catch (IOException e) {
    ...
  }
}

void requestFile()
{
    try {

        FileOutputStream fos = null;

        BufferedOutputStream bos = null;

        DataOutputStream outToServer = new DataOutputStream(MyClient.getOutputStream());

        outToServer.write(encodeIntToByteArray(1)); //SEND THE 1

        outToServer.flush();

        InputStream is = MyClient.getInputStream();

        int remoteFileSize = Integer.parseInt(inFromServer.readLine()); //RECEIVE THE FILESIZE AS STRING

        fos = new FileOutputStream(output);

        bos = new BufferedOutputStream(fos);

        int byteCount = 0;

        int totalByteCount = 0;

        byte[] bytes = new byte[1400];

        while ((byteCount = is.read(bytes)) > 0) {  //RECEIVE THE FILE

            bos.write(bytes, 0, byteCount);

            totalByteCount += byteCount;

        }

        System.out.println("Byte Received "+totalByteCount+" of "+remoteFileSize);

        bos.close();

        fos.close();

        is.close();
    }
catch(...) {

} }

文件test.txt是一个每行都有一个数字的文件:

0
1
2
3
4
...much numbers...
50000

有时,客户端会收到整个文件,有时会收到没有第一部分的文件,如下所示:

60
1860
1861
1862
...much numbers...
50000

从60开始,跳到1860,到50000结束。

我尝试将请求迭代 1000 次,并且 90% 的代码工作,传输所有数据。

谁能帮我理解?

【问题讨论】:

    标签: java qt tcp client-server packet-loss


    【解决方案1】:

    问题在于 IO 流的使用。如果没有正确理解副作用,您不能使用不同的实例:inFromServer & is。您的确切问题是 java.io.BufferedReader#defaultCharBufferSize。

    我建议您在连接时初始化流和阅读器。并在你的课堂上到处使用它们。

    private Socket socket;
    private OutputStream outputStream;
    private Writer outputWriter;
    private InputStream inputStream;
    private Reader inputReader;
    
    public void connect() throws IOException {
        socket = new Socket(..., ...);
        socket.setSoTimeout(60000);
        outputStream = new BufferedOutputStream(socket.getOutputStream()); // Buffered 
        outputWriter = new OutputStreamWriter(outputStream);               // Non-buffered - !important
        inputStream = new BufferedInputStream(socket.getInputStream());    // Buffered
        inputReader = new InputStreamReader(inputStream);                  // Non-buffered - !important
    }
    

    而且对 Java 代码使用 Java 命名约定会更好。

    【讨论】:

      猜你喜欢
      • 2017-02-16
      • 1970-01-01
      • 2019-08-16
      • 2014-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-25
      相关资源
      最近更新 更多