QTcpServer und Unix Sockets

Alles rund um die Programmierung mit Qt
Antworten
Venni
Beiträge: 9
Registriert: 15. Oktober 2007 15:32

QTcpServer und Unix Sockets

Beitrag von Venni »

Hallo,

ich möchte gerne mit einem ganz simplen C-Programm eine TCP-Verbindung zu einem Server aufbauen (also C-Programm als Client) und als Server ein Qt-Programm verwenden. Der Client-Code ist:

Code: Alles auswählen

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>

#define PORT 4711
#define BUF_SIZE 1024

int main(int argc, char *argv[]) {

  int                   sock, run;
  char                  buf[BUF_SIZE];
  struct sockaddr_in    server;
  struct hostent       *hp;
  struct in_addr        ia;

  if (argc != 2) {
    fprintf(stderr,"usage: client <hostname>\n");
    exit(2);
  }

  // create socket
  sock = socket(AF_INET, SOCK_STREAM, 0);
  if (sock < 0) {
    perror("error opening stream socket!");
    exit(1);
  }
  server.sin_family = AF_INET;
  // get internet address of host specified by command line
  hp = gethostbyname(argv[1]);
  if (hp == NULL) {
    fprintf(stderr, "%s unknown host.\n", argv[1]);
    exit(2);
  } else {
    printf("%s is a known host! adress = %d.%d.%d.%d = \n", hp->h_name, hp->h_addr_list[0][0], hp->h_addr_list[0][1], hp->h_addr_list[0][2], hp->h_addr_list[0][3]); //, inet_ntoa(server.sin_addr));

  }

  // copies the internet address to server adress
  bcopy(hp->h_addr, &server.sin_addr, hp->h_length);

  // set port
  server.sin_port = PORT;

  // open connection
  printf("Trying to connect...\n");
  if(connect(sock, (struct sockaddr*)&server,sizeof(struct sockaddr_in)) < 0)
  {
     perror("connecting stream socket");
     exit(1);
  } else {
    printf("connect OK\n");
  }
  printf("OK\n");

 strcpy(buf, "HELLO\n");
 write(sock, buf, strlen(buf));

 /*
  // read input from stdin
  while(run=read(0,buf,BUF_SIZE)) {
    if(run<0) {
      perror("error reading from stdin");
      exit(1);
    }
    // write buffer to stream socket
    if(write(sock,buf,run) < 0)
    {
      perror("writing on stream socket");
      exit(1);
    }
  }
*/

  close(sock);

}
(Mit einem ebenso einfachen Server kann ich auch Zeichenketten von Client zum Server schicken. Aber nicht mit Qt...)

Für den Server habe ich mir mit dem Designer ein Fenster erstellt und folgenden Code erstellt:

gpsview_visualiseTCPDataDialog.h:

Code: Alles auswählen

#ifndef CLASSVISUALISETCPDATADIALOG_H
#define CLASSVISUALISETCPDATADIALOG_H

#include <QTcpServer>
#include <QMessageBox>
#include "ui_visualiseTCPData.h"

class visualiseTCPDataDialog : public QDialog, public Ui_visualiseTCPDataDialog
{
  Q_OBJECT

  public:
  visualiseTCPDataDialog(QWidget *parent = 0);

  private slots:
  void slot_pbStartServerPressed();
  void slot_pbStopServerPressed();
  void slot_NewConnection();

  private:
  QTcpServer *tcpServer;

};

#endif
und

gpsview_visualiseTCPDataDialog.cpp:

Code: Alles auswählen

#include "gpsview_visualiseTCPDataDialog.h"

visualiseTCPDataDialog::visualiseTCPDataDialog(QWidget *parent) : QDialog(parent)
{

  setupUi(this);

  connect( pbStartServer, SIGNAL(clicked()), this, SLOT(slot_pbStartServerPressed()) );
  connect( pbStopServer, SIGNAL(clicked()), this, SLOT(slot_pbStopServerPressed()) );

}

void visualiseTCPDataDialog::slot_pbStartServerPressed() {
  printf("Starting server...\n");

  tcpServer = new QTcpServer(this);

  if (!tcpServer->listen(QHostAddress::Any, 4711)) {
        QMessageBox::critical(this, tr("TCP Server"), tr("Unable to start the server: %1.") .arg(tcpServer->errorString()));
        close();
        return;
     } else {
        QMessageBox::information(this, tr("TCP Server"), tr("The server is running on port %1.\n"
                            "Run the Fortune Client example now.")
                          .arg(tcpServer->serverPort()));

        connect( tcpServer, SIGNAL(newConnection()), this, SLOT(slot_NewConnection()) );

        lbPort->setText( QString( "%1" ).arg(tcpServer->serverPort()) );
     }

   if (tcpServer->isListening()) {
      printf("Server is listening!\n");
   } else {
      printf("Server is not listening!\n");
   }

   if (tcpServer->hasPendingConnections() ) {
      printf("Server has pending connections!\n");
   } else {
      printf("Server has no pending connections!\n");
   }

   connect(tcpServer, SIGNAL(newConnection()), this, SLOT(slot_NewConnection()));

}

void visualiseTCPDataDialog::slot_pbStopServerPressed() {
  printf("Stopping server...\n");

   if (tcpServer->hasPendingConnections() ) {
      printf("Server has pending connections!\n");
   } else {
      printf("Server has no pending connections!\n");
   }

  tcpServer->close();
  lbPort->setText( QString( "?" ) );

   if (tcpServer->isListening()) {
      printf("Server is listening!\n");
   } else {
      printf("Server is not listening!\n");
   }

}

void visualiseTCPDataDialog::slot_NewConnection() {
  printf("New connection!\n");
}
Nachdem ich zuerst den Server gestartet habe ("Start Server"-Button in meinem Fenster), starte ich den Client. Dann erscheint:

Code: Alles auswählen

cc -o client client.c && client localhost
client.c: In function ‘main’:
client.c:42: warning: incompatible implicit declaration of built-in function ‘bcopy’
client.c:58: warning: incompatible implicit declaration of built-in function ‘strcpy’
client.c:59: warning: incompatible implicit declaration of built-in function ‘strlen’
localhost is a known host! adress = 127.0.0.1 =
Trying to connect...
connecting stream socket: Connection refused
Die Warnungen sind doch nicht so tragisch, oder?

Ein "telnet localhost 4711" funktioniert, d.h. slot_NewConnection() zeigt "New connection!"...

Ich weiß, daß beim Server noch einiges fehlt. Ich möchte aber zunächst einfach nur die Verbindung aufbauen können...

Kann mir da jemand helfen?! Vielen Dank im Voraus,
Markus
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

ich würde mir mal errno anschauen -> siehe 'man connect'
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Venni
Beiträge: 9
Registriert: 15. Oktober 2007 15:32

Beitrag von Venni »

Hab den Fehler gerade gefunden:
Wenn ich aus

Code: Alles auswählen

server.sin_port = PORT;
ein

Code: Alles auswählen

server.sin_port = htons(PORT);
mache, dann funktionierts! Warum auch immer...
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Venni hat geschrieben: Warum auch immer...
ich würde sagen: 'Weil es eben so definiert ist'. Sieht man auch wenn man sich mal die Doku zu sockaddr_in anschaut.
Ich habs aber auch nicht gesehen.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Antworten