Winsocks funktioniert nur lokal

Hey, ich habe folgendes Problem
ich habe hier zur Übung ein kleines Programm geschrieben. Einmal
sever.exe und client.exe der Client sendet dabei Strings(von der Usereingabe) per udp an die server.exe welche diese ausgibt jedoch funktioniert dieses nur lokal bedeutet wenn ich das Programm in Internet benutzten will funktioniert es nicht mehr.


Code:
// socket.cpp
#include <windows.h>
#include <cstdlib>
#include <winsock.h>
#include <io.h>
#include <iostream>
#include "socket.h"
using namespace std;

// Konstruktor
Socket::Socket() : m_sock(0) {
   // Winsock.DLL Initialisieren
   WORD wVersionRequested;
   WSADATA wsaData;
   wVersionRequested = MAKEWORD (1, 1);
   if (WSAStartup (wVersionRequested, &wsaData) != 0) {
      throw SockExcept(
             "Fehler beim Initialisieren von Winsock");
   }
}

// Destruktor
Socket::~Socket() {
   if ( is_valid() )
      ::closesocket ( m_sock );
}

// Erzeugt das Socket  - TCP
bool Socket::create() {
   m_sock = ::socket(AF_INET,SOCK_STREAM,0);
   if (m_sock < 0) {
      throw SockExcept("Fehler beim Anlegen eines Socket");
   }
   return true;
}

// Erzeugt das Socket  - UDP
bool Socket::UDP_create() {
   m_sock = ::socket(AF_INET,SOCK_DGRAM,0);
   if (m_sock < 0) {
      throw SockExcept("Fehler beim Anlegen eines Socket");
   }
   return true;
}

// Erzeugt die Bindung an die Serveradresse
// - genauer an einen bestimmten Port
bool Socket::bind( const int port ) {
   if ( ! is_valid() ) {
      return false;
   }
   m_addr.sin_family = AF_INET;
   m_addr.sin_addr.s_addr = INADDR_ANY;
   m_addr.sin_port = htons ( port );

   int bind_return = ::bind ( m_sock,
      ( struct sockaddr * ) &m_addr, sizeof ( m_addr ) );
   if ( bind_return == -1 ) {
      return false;
   }
   return true;
}

// Teile dem Socket mit, dass Verbindungswünsche
// von Clients entgegengenommen werden
bool Socket::listen() const {
   if ( ! is_valid() ) {
      return false;
   }
   int listen_return = ::listen ( m_sock, MAXCONNECTIONS );
   if ( listen_return == -1 ) {
      return false;
   }
  return true;
}

// Bearbeite die Verbindungswünsche von Clients
// Der Aufruf von accept() blockiert solange,
// bis ein Client Verbindung aufnimmt
bool Socket::accept ( Socket& new_socket ) const {
   int addr_length = sizeof ( m_addr );
   new_socket.m_sock = ::accept( m_sock,
      ( sockaddr * ) &m_addr, ( int * ) &addr_length );
   if ( new_socket.m_sock <= 0 )
      return false;
   else
      return true;
}

// Baut die Verbindung zum Server auf
bool Socket::connect( const string host, const int port ) {
   if ( ! is_valid() )
      return false;
   struct hostent *host_info;
   unsigned long addr;
   memset( &m_addr, 0, sizeof (m_addr));
   if ((addr = inet_addr( host.c_str() )) != INADDR_NONE) {
       /* argv[1] ist eine numerische IP-Adresse */
       memcpy( (char *)&m_addr.sin_addr, &addr,
                sizeof(addr));
   }
   else {
       /* Für den Fall der Fälle: Wandle den Servernamen *
        * bspw. "localhost" in eine IP-Adresse um        */
       host_info = gethostbyname( host.c_str() );
       if (NULL == host_info) {
          throw SockExcept("Unbekannter Server");
       }
       memcpy( (char *)&m_addr.sin_addr, host_info->h_addr,
                host_info->h_length);
   }
   m_addr.sin_family = AF_INET;
   m_addr.sin_port = htons( port );

   int status = ::connect ( m_sock,
      ( sockaddr * ) &m_addr, sizeof ( m_addr ) );

  if ( status == 0 )
    return true;
  else
    return false;
}

// Daten versenden via TCP
bool Socket::send( const string s ) const {
   int status = ::send ( m_sock, s.c_str(), s.size(),  0 );
   if ( status == -1 ) {
      return false;
   }
   else {
      return true;
   }
}

// Daten empfangen via TCP
int Socket::recv ( string& s ) const {
  char buf [ MAXRECV + 1 ];
  s = "";
  memset ( buf, 0, MAXRECV + 1 );

  int status = ::recv ( m_sock, buf, MAXRECV, 0 );
  if ( status > 0 || status != SOCKET_ERROR ) {
     s = buf;
     return status;
  }
  else {
     throw SockExcept("Fehler in Socket::recv");
     return 0;
  }
}

// Daten versenden via UDP
bool Socket::UDP_send( const string addr, const string s, const int port ) const {
   struct sockaddr_in addr_sento;
   struct hostent *h;
   int rc;

   h = gethostbyname(addr.c_str());
   if (h == NULL) {
      throw SockExcept("Unbekannter Host?");
   }
   addr_sento.sin_family = h->h_addrtype;
   memcpy ( (char *) &addr_sento.sin_addr.s_addr,
            h->h_addr_list[0], h->h_length);
   addr_sento.sin_port = htons (port);
   rc = sendto( m_sock, s.c_str(), s.size(), 0,
                 (struct sockaddr *) &addr_sento,
                  sizeof (addr_sento));
   if (rc == SOCKET_ERROR) {
      throw SockExcept(
         "Konnte Daten nicht senden - sendto()");
   }
   return true;
}

// Daten empfangen vie UDP
int Socket::UDP_recv( string& s ) const {
   struct sockaddr_in addr_recvfrom;
   int len, n;
   char buf [ MAXRECV + 1 ];
   s = "";
   memset ( buf, 0, MAXRECV + 1 );
   len = sizeof (addr_recvfrom);
   n = recvfrom ( m_sock, buf, MAXRECV, 0,
                   (struct sockaddr *) &addr_recvfrom, &len );
   if (n == SOCKET_ERROR){
      throw SockExcept("Fehler bei recvfrom()");
      return 0;
   }
   else {
      s = buf;
      return n;
   }
}

// Winsock.dll freigeben
void Socket::cleanup() const {
   /* Cleanup Winsock */
   WSACleanup();
}

// Socket schließen und Winsock.dll freigeben
bool Socket::close() const {
   closesocket(m_sock);
   cleanup();
   return true;
}

Code:
/* socket.h für MS-Windows */
#ifndef SOCKET_H_
#define SOCKET_H_
#include <string>
#include <winsock.h>
#include <io.h>
using namespace std;

// Max. Anzahl Verbindungen
const int MAXCONNECTIONS = 5;
// Max. Anzahl an Daten die aufeinmal empfangen werden
const int MAXRECV = 1024;

// Die Klasse Socket
class Socket {
   private:
   // Socketnummer (Socket-Deskriptor)           
   int m_sock; 
   // Struktur sockaddr_in
   sockaddr_in m_addr;
   
   public:
   // Konstruktor
   Socket();
   // virtueller Destruktor
   virtual ~Socket();

   // Socket erstellen - TCP
   bool create();
   // Socket erstellen - UDP
   bool UDP_create();
   bool bind( const int port );
   bool listen() const;
   bool accept( Socket& ) const;
   bool connect ( const string host, const int port );
   // Datenübertragung - TCP
   bool send ( const string ) const;
   int recv ( string& ) const;
   // Datenübertragung - UDP
   bool UDP_send( const string, const string,
                  const int port ) const;
   int UDP_recv( string& ) const;
   // Socket schließen
   bool close() const;
   // WSAcleanup()
   void cleanup() const;
   bool is_valid() const { return m_sock != -1; }
};

// Exception-Klasse
class SockExcept {
   private:
   string except;
   
   public:
   SockExcept( string s ) : except( s ) {};
   ~SockExcept() {};
   string get_SockExcept() { return except; }
};

Der Server:
Code:
#include <iostream>
#include "socket.h"

using namespace std;

int main()
{

        Socket server,a;
        string s;
        server.UDP_create();
        server.bind(15000);
        while( true ) {
         string s;
         server.UDP_recv(s);
         cout << "Daten: " << s<<endl;
        }

}
Der Client
Code:
#include <iostream>
#include "socket.h"

using namespace std;

int main()
{

    string host;
    Socket asd;
    asd.UDP_create();
    asd.bind( 15000);
    cout << "Ip: ";
    getline(cin,host, '\n');
    while ( true) {
    string s;
    cout << "\nDaten: ";
    getline( cin, s, '\n');
    asd.UDP_send(host,s, 15000);
    }


   return 0;
}

Habe einfach keine Ahnung woran das liegt.
Wäre super wenn mir jemand helfen könnte!
 
Rechner, die -so wie meist der Fall- sich hinter einem Router verstecken, sind nicht direkt erreichbar -> dem Router muss mitgeteilt werden, wohin die ankommenden Pakete weitergeschickt werden sollen. Dh. du müsstest mit deinem Router ( Stichworte -> NAT, PortForwarding ) rumspielen :)

Ich kenne keine andere (edit: saubere) Lösung.

MfG
 
mhm gibt es da keine einfach software seitige lösung?
Denn wenn ich mitm meinem Browser im Internet bin und eine Anfrage an google.de schicke weiß der Router bei der Antwort doch auch dass ich das Packet (auf Port 80) empfangen möchte und nicht jemand anders der über den gleichen Router auch surft.
Trotzdem schonmal danke.

mfg virus
 
Original von Virus
mhm gibt es da keine einfach software seitige lösung?
Denn wenn ich mitm meinem Browser im Internet bin und eine Anfrage an google.de schicke weiß der Router bei der Antwort doch auch dass ich das Packet (auf Port 80) empfangen möchte und nicht jemand anders der über den gleichen Router auch surft.
Trotzdem schonmal danke.

mfg virus

Du verstehst das glaub ich falsch^^

Wenn du eine Connection zu google aufbaut, muss google den Port offen haben .

So wenn du und noch ein PC im Lan seid, und ihr einen Port offen habt, weiß der Router nicht, zu welchem er die eingehenden Anfragen schicken soll, und blockt diese ab

d.h. du musst im Router einstellen, dass der Port auf deinen PC weitergeleitet wird.
 
Original von Virus
mhm gibt es da keine einfach software seitige lösung?
Denn wenn ich mitm meinem Browser im Internet bin und eine Anfrage an google.de schicke weiß der Router bei der Antwort doch auch dass ich das Packet (auf Port 80) empfangen möchte und nicht jemand anders der über den gleichen Router auch surft.
Trotzdem schonmal danke.

mfg virus
Die Portweiterleitung läst sich recht einfach in der routerkonfiguration einstellen.

Wen du mit einen browser eine seite wie z.b. google aufrufst baut dein pc über den router eine verbindung zu den server auf und der server schickt über die geöffnete verbindung seine daten wieder zurück.
 
Ich hab des schon richtig verstanden, hab mich vielleicht falsch ausgedrückt also noch ein Versuch.
Also zu meinem Programm ich schicke per udp ein Paket an einen Server welcher dieses empfängt jetzt möchte ich das bei dieser Übermittlung angegeben wird wohin das Paket kommen soll.
Also praktisch dass der der Router weiß, dieses Paket soll dorthin weitergeleitet werden. Also gibt es einen möglichkeit (eventuell anstatt udp tcp verwenden) dass ich mit einem c++ code dem packet mitgebe wohin es muss bzw wohin es vom Router weitergeleitet wird.
Es muss doch möglich sein eine Verbindung (tcp) zu einem pc zu erstellen welcher hinter einem Router sitzt, oder per udp einfach an so einen PC zu senden?

Oder ist es so das dies schlichtweg so nicht möglich ist, und erst wenn ich bei der Anfrage an einen Server sende, welcher keinen Router sondern eine Feste öffentliche ip/Standleitung hat, und bei diesem eine Verbindung zu mir herstelle. Auch eine Antwort kommen kann bei welcher mein Router weiß diese muss wo auch immer hin weitergeleitet werden. Da ja eine Verbindung zu mir hergestellt ist.

Jedoch funktioniert udp dann ja gar nicht?! Da keine Verbindung hergestellt wird kann ich nur auf einen PC/server welcher nicht hinter einem Router hängt senden.

Es gibt doch bestimmt eine Lösung ohne die Routerkonfiguration, denn damit wäre das Programm ja völlig unkompatibel da es nur bei mir funktioniert und nirgends sonst, da der Router nirgends weis dass dieses Programm zu diesem Port gehört. Oder gibt es eine Andere möglichkeit per c++ dem router zu sagen wo das Programm lauscht und was er alles zu dem Programm weiterleiten soll?

Ich Hoffe ich habe mich klar ausgedrückt.

mfg virus
 
Original von Virus
Ich hab des schon richtig verstanden, hab mich vielleicht falsch ausgedrückt also noch ein Versuch.
Also zu meinem Programm ich schicke per udp ein Paket an einen Server welcher dieses empfängt jetzt möchte ich das bei dieser Übermittlung angegeben wird wohin das Paket kommen soll.
Also praktisch dass der der Router weiß, dieses Paket soll dorthin weitergeleitet werden. Also gibt es einen möglichkeit (eventuell anstatt udp tcp verwenden) dass ich mit einem c++ code dem packet mitgebe wohin es muss bzw wohin es vom Router weitergeleitet wird.
Es muss doch möglich sein eine Verbindung (tcp) zu einem pc zu erstellen welcher hinter einem Router sitzt, oder per udp einfach an so einen PC zu senden?

Oder ist es so das dies schlichtweg so nicht möglich ist, und erst wenn ich bei der Anfrage an einen Server sende, welcher keinen Router sondern eine Feste öffentliche ip/Standleitung hat, und bei diesem eine Verbindung zu mir herstelle. Auch eine Antwort kommen kann bei welcher mein Router weiß diese muss wo auch immer hin weitergeleitet werden. Da ja eine Verbindung zu mir hergestellt ist.

Jedoch funktioniert udp dann ja gar nicht?! Da keine Verbindung hergestellt wird kann ich nur auf einen PC/server welcher nicht hinter einem Router hängt senden.

Es gibt doch bestimmt eine Lösung ohne die Routerkonfiguration, denn damit wäre das Programm ja völlig unkompatibel da es nur bei mir funktioniert und nirgends sonst, da der Router nirgends weis dass dieses Programm zu diesem Port gehört. Oder gibt es eine Andere möglichkeit per c++ dem router zu sagen wo das Programm lauscht und was er alles zu dem Programm weiterleiten soll?

Ich Hoffe ich habe mich klar ausgedrückt.

mfg virus

Es geht höchstens noch über uPNP

Damit kannst du den Router veranlassen, den Port weiterzuleiten
 
kann man nicht irgentwie mit seinem Programm die portweiterleitung auf dem router aktivieren, damit er die Verbindung über TCP herstellen kann??? Es gibt doch auf andere p2p chat-programme, machen die das alle auch über uPNP?

mfg selig
 
Zurück
Oben