2016-10-17 5 views
0

Der folgende Code hat einen TCP-Client in C und TCP-Server in Qt C++. Mein Problem ist, dass ich TCP für Zuverlässigkeit verwende, aber es hat Datenverluste (nicht Paket). In meinem Hauptcode, wenn ich TCP-Client zum Senden von Daten ausführen, empfängt TCP-Server nur ein Paket. Wenn ich dem Client zwischen den einzelnen Paketübertragungen sleep(1); hinzufüge, empfängt der TCP-Server Daten. Client und Server werden auf demselben Computer ausgeführt.TCP-Server empfängt keine Daten richtig

Um die Frage zu vereinfachen und kann nicht zu großen Code hier, ich habe den folgenden Code, der schneller, aber es dauert Verluste 10-15 Bytes des Pakets.

TCP C Client

main.c

#include "socket_handler.h" //I didn't put the all includes here 
#define  PORT    22208 
//tcp server 
int main(void) 
{ 
    int sockfd; 
    uint32_t senderAddress = 2130706433; //127.0.0.1 
    if(connect_to_server_w_uint(&sockfd, senderAddress, PORT) < 0){ 
     printf("error at line 454\n"); 
     exit(1); 
    } 

    char data[] = "124b00068c158f$321$52712304$13.212779$0$O$0$0$b4$1$0$3$0$0$0$0$11$0$7$0$1$fe$f1$aaa9fffffffffd80$2132b00$eb460b5e$1$1$2016-02-22 03:01:00$0000-00-00 00:00:00$321$24754$321$13132$1$98$0$5.1$0$3c$64$1$96$4d$3e8$38$2$46$dc$4$3$f6$e6$17$0$e6$d3$1$0$e6$d3$2$0£"; 
    char buffer[512]; 

    int i=0; 
    for(i=0; i<1000; i++){ 
     bzero(buffer, 512); 
     sprintf(buffer, "%d***%s -----",i,data); 
     send_data_to_server(&sockfd, buffer, strlen(data) +1); 
     printf("[%d]: data is sent\n", i); 
    } 
    close_connection(&sockfd); 

    return 0; 
} 

socket_handler.c

int connect_to_server(int *sockfd , struct in_addr senderAddress, uint16_t destPort){ 
    struct sockaddr_in serv_addr; 

    *sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (*sockfd < 0) 
     //error("ERROR opening socket"); 

    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr = senderAddress; 
    serv_addr.sin_port = htons(destPort); 

    if (connect(*sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0){ 
     printf("connection error line 1413\n"); 
     close(*sockfd); 
     return -1; 
    } 

    return 0; 
} 


int connect_to_server_w_uint(int *sockfd, uint32_t senderAddress, uint16_t destPort){ 
    struct sockaddr_in serv_addr; 

    *sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (*sockfd < 0){ 
     printf("ERROR opening socket"); 
     close(*sockfd); 
     return -1; 
    } 

    bzero((char *) &serv_addr, sizeof(serv_addr)); 
    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_addr.s_addr = htonl(senderAddress); 

    serv_addr.sin_port = htons(destPort); 
    if (connect(*sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
    { 
     printf("ERROR connecting"); 
     close(*sockfd); 
     return -1; 
    } 

    return 0; 
} 

int send_data_to_server(int *sockfd, char *message, uint16_t msgLength){ 
    int n = write(*sockfd, message, msgLength); 
    if (n < 0){ 
     printf("ERROR writing to socket"); 
     return -1; 
    } 
    return 0; 
} 

int close_connection(int *sockfd){ 
    close(*sockfd); 
    return 0; 
} 

Qt C++ TCP Server

mainwindow.cpp

class MainWindow; 
} 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 

private slots: 
    void ParseThePacket(QByteArray data); 

private: 
    Ui::MainWindow *ui; 

    Server *server; 
}; 

Client.h

class Client : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit Client(QObject *parent = 0); 

public slots: 
    bool connectToHost(QString host); 
    bool writeData(QByteArray data); 

private: 
    QTcpSocket *socket; 

}; 

Server.cpp

Server::Server(QObject *parent) : QObject(parent) 
{ 
    server = new QTcpServer(this); 
    connect(server, SIGNAL(newConnection()), this, SLOT(newConnection())); 
    if(server->listen(QHostAddress::Any, PORT)){ 
     qDebug() << "tcp server started!"; 
    }else{ 
     qDebug() << "tcp server couldn't start listening"; 
    } 
} 

void Server::newConnection() 
{ 
    qDebug() << "new connection"; 
    while (server->hasPendingConnections()) 
    { 
     socket = server->nextPendingConnection(); 
     connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead())); 
     connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected())); 
    } 
} 

void Server::disconnected() 
{ 
    qDebug() << "disconnected"; 
    socket->deleteLater(); 
} 

void Server::readyRead() 
{ 
    qDebug() << "readyRead"; 

    QByteArray buffer = socket->readAll(); 
    emit dataReceived(buffer); 
} 

Hier ist ein Beispiel für die Ausgabe von dem TCP-Server (Das Ende des qDebug() -Ausgabe):

00: 00: 00 321 24754 $ 321 13132 $ $ $ 1 $ 98 $ 0 $ $ 5,1 $ 0 3c $ 64 $ 1 $ 96 $ $ 4d $ 3E8 38 $ 2 $ 46 $ $ dc 4 $ $ $ 3 f6 $ e6 $ 17 $ 0 $ e6 $ d3 $ 1 $ 0 $ e6 $ d3 $ 996 *** 124b00068c158f $ 321 $ 52712304 $ 13.212779 $ 0 $ O $ 0 $ 0 $ b4 $ 1 $ 0 $ 3 $ 0 $ 0 $ 0 $ 0 $ 11 $ 0 $ 7 $ 0 $ 1 $ fe $ f1 $ aaa9fffffffffd80 $ 2132b00 $ eb460b5e $ 1 $ 1 $ 2016-02-22 03: 01: 00 $ 0000-00-00 00: 00: 00 $ 321 $ 24754 $ 321 $ 13132 $ 1 $ 98 $ 0 $ 5.1 $ 0 $ 3c $ 64 $ 1 $ 96 $ 4d $ 3e8 $ 38 $ 2 $ 46 $ dc $ 4 $ 3 $ f6 $ e6 $ 17 $ 0 $ e6 $ d3 $ 1 $ 0 $ e6 $ d3 $ 997 *** 124b00068c158f $ 321 $ 52712304 $ 13.212779 $ 0 $ O $ 0 $ 0 $ b4 $ 1 $ 0 $ 3 $ 0 $ 0 $ 0 $ 0 $ 11 $ 0 $ 7 $ 0 $ 1 $ fe $ f1 $ aaa9fffffffffd80 $ 2132 b00 $ eb460b5e $ 1 $ 1 $ 2016-02-22 03: 01: 00 $ 0000-00-00 00: 00: 00 $ 321 $ 24754 $ 321 $ 13132 $ 1 $ 98 $ 0 $ 5.1 $ 0 $ 3c $ 64 $ 1 $ 96 $ 4d $ 3e8 $ 38 $ 2 $ 46 $ dc $ 4 $ 3 $ f6 $ e6 $ 17 $ 0 $ e 6 $ d3 $ 1 $ 0 $ e6 $ d3 $ 998 *** 124b00068c158f $ 321 $ 52712304 $ 13.212779 $ 0 $ O $ 0 $ 0 $ b4 $ 1 $ 0 $ 3 $ 0 $ 0 $ 0 $ 0 $ 11 $ 0 $ 7 $ 0 $ 1 $ fe $ f1 $ aaa9fffffffffd80 $ 2132b00 $ eb460b5e $ 1 $ 1 $ 2016- 02-22 03: 01: 00 $ 0000-00-00 00: 00: 00 $ 321 $ 24754 $ 321 $ 13132 $ 1 $ 98 $ 0 $ 5.1 $ 0 $ 3c $ 64 $ 1 $ 96 $ 4d $ 3e8 $ 38 $ 2 $ 46 $ dc $ 4 $ 3 $ f6 $ e6 $ 17 $ 0 $ e6 $ d3 $ 1 $ 0 $ e6 $ d3 $ 999 *** 124b00068c158f $ 321 $ 52712304 $ 13.212779 $ 0 $ O $ 0 $ 0 $ b4 $ 1 $ 0 $ 3 $ 0 $ 0 $ 0 $ 0 $ 11 $ 0 $ 7 $ 0 $ 1 $ fe $ f1 $ aaa9fffffffffd80 $ 2132b00 $ eb460b5e $ 1 $ 1 $ 2016-02-22 03: 01: 00 $ 0000-00-00 00: 00: 00 $ 321 $ 24754 $ 321 $ 13132 $ 1 $ 98 $ 0 $ 5.1 $ 0 $ 3c $ 64 $ 1 $ 96 $ 4d $ 3e8 $ 38 $ 2 $ 46 $ dc $ 4 $ 3 $ f6 $ e6 17 0 $ $ $ $ e6 d3 $ 1 $ 0 $ e6 $ d3 $“ getrennt

Frage 1 Vergleicht man die ursprüngliche Nachricht, fehlt "1 $ 0 $ e6 $ d3 $ 2 $ 0 £" Teil der (14 Byte) gesendeten Daten. Was ist der Grund für die fehlende Nachricht?Wie man den Code repariert, dass der TCP-Server die vollständigen Daten empfängt.

Frage 2 Wie ich am Anfang erwähnt, dass ich den gleichen Code als Teil eines großen Code und TCP Server verwende empfangen Pakete, wenn I eingeschläfert (1) zwischen jeder Paketübertragung (es anders empfängt nur das erste Paket). Was ist der Grund dafür und wie kann man es lösen?

Ich beobachtete die Paketübertragung auf Wireshark, dass alle TCP-Pakete erfolgreich gesendet werden, aber es scheint, dass der Empfangsteil ein Problem hat.

Ich bin mit Ubuntu 15.04, Kernel 3.19.0-69-generic, gcc Version 4.9.2

+1

Wow, viel Code. Präsentieren Sie bitte [MCVE]. –

Antwort

5
int n = write(*sockfd, message, msgLength); 

if (n < 0){ 

Du bist gerade nur, dass write() keinen negativen Wert zurückkehrte, einen Fehler anzeigt.

Ein write() zu einem Socket garantiert jedoch nicht, dass alle angeforderten Bytes geschrieben werden. write() auf einem Socket kann einen positiven Wert zurückgeben, weniger als msgLength hier, was darauf hinweist, dass weniger als die angeforderten Bytes geschrieben wurden. Dies ist im Einzelnen in der Handbuchseite write() dokumentiert.

Sie ignorieren diese Möglichkeit, und das ist wahrscheinlich der Grund, warum Sie Ihre Daten vermissen. Es liegt an Ihnen, in diesem Fall herauszufinden, was zu tun ist. Der übliche Ansatz besteht darin, einfach zurückzugehen und zu versuchen, die verbleibenden Bytes zu schreiben (die wiederum möglicherweise nicht vollständig geschrieben sind).

Ebenso, wenn Sie von einem Socket lesen, können Sie nicht garantieren, dass alles, was vom Absender in den Socket geschrieben wurde, in einem Zug gelesen wird. Es liegt an Ihnen, zu überprüfen, ob Ihr Leser alles gelesen hat, was zu lesen ist, und wenn der Leser mehr Daten erwartet, lesen Sie weiter aus dem Socket, bis er empfangen wird.

+0

Ja, ich sehe auf Wireshark, dass das gesendete Paket fehlt. Vielen Dank. – sven

1

ReadAll liest gerade alle Daten zur Verfügung, die aktuellen Moment.