2014-11-29 2 views
0

QT/C++ 서버와 Java 클라이언트가 있습니다. 클라이언트는 서버에 파일을 요청하고 서버는 스트림을 클라이언트에 보냅니다. 문제는 TCP 전송 (로컬 호스트에서도)에서 일부 패킷을 잃어버린 것입니다.QT - Java 소켓 손실 데이터

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입니다 : 때때로, 클라이언트가 288890.

의 280,705 바이트를받을 수 있습니다 서버입니다

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

그리고 이것은 자바 클라이언트입니다 :

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 각 줄에 번호가있는 파일입니다

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

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

때로는 클라이언트가 전체 파일을 수신, 때로는이 같은 첫 번째 부분없이 파일을 수신

60에서 시작하여 1860으로 건너 뛰고 50000으로 끝납니다.

요청을 1000 번 반복하고 코드가 작동하는 시간의 90 %를 반복하려고하면 모든 데이터가 전송됩니다.

누군가 나를 이해하도록 도와 줄 수 있습니까?

답변

0

IO 스트림을 사용하는 데 문제가 있습니다. 부작용을 제대로 이해하지 않으면 다른 인스턴스를 사용할 수 없습니다. inFromServer &입니다. 정확한 문제는 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 명명 규칙을 사용하는 것이 좋습니다.