isabell20
Anmeldungsdatum: 26. November 2019
Beiträge: Zähle...
|
Guten Tag Ubuntuusers,
Ich bin derweil dabei, eine UDP Kommunikation zwischen einem Windows Rechner und einem Linux-Rechner (ubuntu) herzustellen.
An beiden Rechnern ist jeweils ein USB-Modem mit integrierter SIM-Karten angeschlossen.
Nach einiger Recherche und mehreren Beispiel-Codes, habe ich seitens Linux-Rechner noch einige Probleme beim erstellen des Sockets. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 | /************* UDP SERVER CODE *******************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
int main(){
int udpSocket, nBytes;
char buffer[1024];
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
int i;
/*Create UDP socket*/
udpSocket = socket(PF_INET, SOCK_DGRAM, 0);
/*Configure settings in address struct*/
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*Bind socket with address struct*/
bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*Initialize size variable to be used later on*/
addr_size = sizeof serverStorage;
while(1){
/* Try to receive any incoming UDP datagram. Address and port of
requesting client will be stored on serverStorage variable */
nBytes = recvfrom(udpSocket,buffer,1024,0,(struct sockaddr *)&serverStorage, &addr_size);
/*Convert message received to uppercase*/
for(i=0;i<nBytes-1;i++)
buffer[i] = toupper(buffer[i]);
/*Send uppercase message back to client, using serverStorage as the address*/
sendto(udpSocket,buffer,nBytes,0,(struct sockaddr *)&serverStorage,addr_size);
}
return 0;
}
|
Zu dem oben genannten Code habe ich die Frage, wie ich denn den Server mit dem Client verbinde, da der Code das Terminal ohne jederlei Inhalte öffnet (Ich vermute, dass gar keine Verbindung hergestellt wird).
Der Server soll der Linux-rechner sein, der Client der Windows-Rechner.
Was verwende ich denn als Serveradresse, und was verwende ich als Port? Die Verbindung sollte rein theoretisch über die SIM-Karten erfolgen, verwende ich dann die IP-Adresse des Modems? Ich weiß, dass meine Fragen sehr Allgemein sind, und auch vielleicht keiner auf die schnelle weiterhelfen kann, aber ich dachte ich probier mein Glück hier, nachdem ich unzählige Seiten im Internet danach durchstöbert und keine hilfreichen Beiträge gefunden habe.
|
Vain
Anmeldungsdatum: 12. April 2008
Beiträge: 2503
|
Du hast hier diese beiden Zeilen: serverAddr.sin_port = htons(7891);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); Die erste legt den Port auf 7891 fest, die zweite bindet das Socket auf die IP 127.0.0.1. Das ist leider localhost und von außen nicht erreichbar. Hier musst du entweder gezielt die gewünschte IP eintragen (muss man separat erfragen) oder du nimmst 0.0.0.0 für „lausche überall“ (Obacht, kann unerwünscht sein). Dass das Programm nichts ausgibt, ist zu erwarten. Es öffnet den Socket und schickt alles, das es empfängt, im Uppercase zurück. Du könntest also exemplarisch in einem Terminal dein Programm hier starten und in einem anderen das: $ date | nc -u 127.0.0.1 7891
MON 02 DEC 2019 07:09:40 PM CET (Mein nc ist jetzt ein OpenBSD-netcat. Kann sein, dass das von GNU minimal anders ist.) Wie man sieht, kommt da eine Ausgabe in Großbuchstaben zurück. ☺ (Der Vollständigkeit halber: Der Compiler gibt zwei Warnungen wegen unbenutzter Variablen aus und es werden im Code nirgendwo Rückgabewerte geprüft. Gerade letzteres muss man in C unbedingt tun, weil man sonst im Fehlerfall mit unbekantem Zustand weitermacht, was böse enden kann.)
|
isabell20
(Themenstarter)
Anmeldungsdatum: 26. November 2019
Beiträge: 10
|
Vielen Dank für die schnelle Antwort. Vain schrieb: Hier musst du entweder gezielt die gewünschte IP eintragen (muss man separat erfragen) oder du nimmst 0.0.0.0 für „lausche überall“ (Obacht, kann unerwünscht sein).
Wie erfrage ich die IP denn separat? Und wie ermittle ich den richtigen Port? Und wenn ich jetzt einen Client-Code auf meinem Windows-Rechner erstelle, welcher beliebige Daten sendet, wie stelle ich die Verbindung zu meinem Server (linux-Rechner) her.
Kann ich denn testen, ob mein Linux und mein Windows Rechner über UDP kommunizieren können? Dass zwei Variablen nicht verwendet werden, ist mir bewusst. Diese habe ich auch bereits auskommentiert.
|
Vain
Anmeldungsdatum: 12. April 2008
Beiträge: 2503
|
isabell20 schrieb: Wie erfrage ich die IP denn separat?
Das mit der IP kommt so ein bisschen auf deinen Anwendungsfall an. So ein typischer Server-Daemon unter Linux wird ja meistens konfiguriert, sprich, du sagst ihm: „Lausche auf IP $x.“ Damit ist das Thema üblicherweise durch. Vermute ich das richtig, dass du automatisch das richtige Interface finden wollen würdest? Das, was zum USB-Modem gehört? Ganz spontan fällt mir getifaddrs ein und dann nach dem Namen des Interfaces filtern … Hmm. Ist tendenziell etwas wackelig, nach solchen Namen zu gehen. Wenn man mehr Details wissen will, puh, dann muss man sich wohl mit udev auseinandersetzen?
Und wie ermittle ich den richtigen Port?
Den kannst du frei wählen ab 1024 (darunter müsste dein Programm mit root-Rechten laufen bzw. zumindest binden).
Und wenn ich jetzt einen Client-Code auf meinem Windows-Rechner erstelle, welcher beliebige Daten sendet, wie stelle ich die Verbindung zu meinem Server (linux-Rechner) her.
Kann ich denn testen, ob mein Linux und mein Windows Rechner über UDP kommunizieren können?
Hm, weiß nicht, können die sich pingen? Dann können sie (von etwaigen Firewalls abgesehen) auch normal TCP oder UDP miteinander reden. Gleich vorweg: Keine Ahnung von Socket-Code unter Windows. Das ist ewig her, seit ich das (dilettantisch) gemacht habe.
|
isabell20
(Themenstarter)
Anmeldungsdatum: 26. November 2019
Beiträge: 10
|
Inzwischen hat das Rüberschicken einer Zeichenkette funktioniert (jedoch nur kabelgebunden). Das ganze läuft dann über das Hochschulnetzwerk und bei Eingabe der lokalen IP-Adresse des Servers (Ubuntu), funktioniert eine Verbindung. Leider klappt es aber noch nicht kabellos, was ja für die gewünschte Anwendung notwendig ist. Das USB-Modem verfügt über eine vom PC aus sichtbare IP, die von außen natürlich nicht sichtbar ist. Im Web-Interface des Huawei-Sticks findet sich noch eine WAN-IP. Dann habe ich im Web nach unserer IP gesucht mit www.icanhazip.de. Da kommt dann wieder eine neue IP, die lässt sich aber in Stuttgart orten und nicht bei mir in Ulm. Scheint wohl ein Gateway des Providers zu sein... Jedenfalls klappt es auch mit diesen beiden Adressen nicht. Eine gründliche Recherche im Web hat ergeben, dass das ganze wohl am Port Forwarding scheitert, weil bei dem USB-Modem die Ports nicht von außen zugänglich sind (wahrscheinlich durch den Provider gesperrt). Das Problem scheinen sehr viele mit USB-Modems zu haben, aber leider hat keiner eine Lösung parat. Ich werde noch ein bisschen weitersuchen nach einer Lösung... Vielleicht hat ja hier noch jemand eine Idee... Ansonsten versuche ich es die Tage mal mit einem lokalen LTE-Router in der Hoffnung, dass hier die Portweiterleitung möglich ist. Viele Grüße, Isabell
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
isabell20 schrieb: Das Problem scheinen sehr viele mit USB-Modems zu haben, aber leider hat keiner eine Lösung parat.
Die NAT macht normalerweise der Mobilfunkanbieter (vgl. z.B. Carrier-grade_NAT) - die Clients sind dadurch nicht unter einer öffentlichen IP erreichbar. Ich werde noch ein bisschen weitersuchen nach einer Lösung... Vielleicht hat ja hier noch jemand eine Idee...
Beide Rechner könnten eine SSH- oder VPN-Verbindung zu einem von beiden erreichbaren Server aufbauen, durch die man dann die UDP-Kommunikation tunneln könnte - das hat dann auch den Vorteil, dass nicht jeder mitlesen kann, was man da an Daten überträgt.
|
isabell20
(Themenstarter)
Anmeldungsdatum: 26. November 2019
Beiträge: 10
|
Guten Morgen, wenn ich richtig verstehe brauche ich für den VPN-Tunnel also einen dritten PC, als Server? Und sind die beinen anderen Rechner dann jeweils Clients?
|
seahawk1986
Anmeldungsdatum: 27. Oktober 2006
Beiträge: 11176
Wohnort: München
|
Ja genau, die Idee ist, dass sich beide Rechner zu einem dritten Rechner verbinden, der öffentlich erreichbar ist und als (VPN-)Server dient und die Clients dann innerhalb des virtuellen Netzes Daten austauschen. Für UDP über SSH müsste man etwas tricksen, weil SSH TCP-basiert arbeitet (z.B. http://zarb.org/~gc/html/udp-in-ssh-tunneling.html oder https://manpages.ubuntu.com/manpages/bionic/en/man1/udptunnel.1.html) und bräuchte eine Kombination einem reversen SSH-Tunnel von einem Client zum Server und einem vorwärts gerichteten Tunnel vom zweiten Client über den Server auf den reversen Tunnel des ersten Client.
|
kB
Supporter, Wikiteam
Anmeldungsdatum: 4. Oktober 2007
Beiträge: 8554
Wohnort: Münster
|
Rechner, die nicht direkt mit dem Internet verbunden sind, können zwar möglicherweise selbst Ziele im Internet erreichen, sind aber aus dem Internet selbst nicht erreichbar. Diese Situation liegt vor, wenn sich der Rechner aus Sicht des Internet hinter einem Router mit NAT befindet. Dies betrifft also z.B. jeden Rechner, der das Internet …
per DSL hinter einem kundenseitigen Router wie z.B. Fritzbox o.ä. oder über ein Telefonnetz (immer CGN) erreicht, oder bei dem der Provider aus anderen Gründen CGN (Carrier Grade NAT) anwendet.
Als technische Krücke zur Überwindung dieser durch die technische Krücke NAT verursachten Probleme kann man bei IPv4 einsetzen:
Port-Forwarding: Das muss man aber auf allen Routern mit NAT zwischen den beiden Stationen machen. Bei CGN kann man das also nicht anwenden. Hole Punching: Dabei werden in der Firewall der Router automatisch Regeln für die beiden Stationen hinzugefügt. Relay Server: Beide Stationen melden sich bei diesem an und erfahren damit, wie sie die Gegenstation erreichen können. Der eigentliche Datenaustausch erfolgt aber dann zwischen den beiden Stationen direkt. Alle Telefongespräche über VoIP (und das sind alle) funktionieren z.B. so. Der Relay Server arbeitet nur als Makler beim Aufbau der Verbindung, lässt sich aber für die Dauer der Verbindung bezahlen.
Oder man verwendet IPv6 statt IPv4, dann gibt es kein NAT.
|