Seite 1 von 1

QTcpServer und Unix Sockets

Verfasst: 15. Oktober 2007 16:02
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

Verfasst: 16. Oktober 2007 10:46
von Christian81
ich würde mir mal errno anschauen -> siehe 'man connect'

Verfasst: 16. Oktober 2007 13:19
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...

Verfasst: 16. Oktober 2007 13:44
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.