Client->Server zwischen zwei Rechnern im Wlan

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Pandorarain
User
Beiträge: 5
Registriert: Freitag 24. Februar 2017, 16:53

Hallo Zusammen.

Ich beschäftige mich seit kurzer Zeit mit sockets und bin im Internet auf das folgende Beispiel gestossen:
Rechner 1 Server:

Code: Alles auswählen

import socket

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print('waiting for client')
serversocket.bind(('192.168.1.104', 5000)) 
serversocket.listen(0)

(clientsocket, adress) = serversocket.accept()
print('client connected')

while True:
	msg = clientsocket.recv(1024)
	msg = msg.decode()
	print(msg)
	
	ans = 'Server hat folgende Anfrage erhalten: '+ msg
	ans = ans.encode()
	clientsocket.send(ans)
	
clientsocket.close()
serversocket.close()
Rechner 2 Client:

Code: Alles auswählen

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.1.104', 5000))

while True:
	msg = str(input('Was moechten Sie dem Server sagen? '))
	msg = msg.encode()
	s.send(msg)
	
	msg = s.recv(1024)
	msg = msg.decode()
	print('Serverantwort: ' + msg)
	
s.close()
Wenn beide Programme auf dem gleichen Rechner laufen, funktioniert es eigentlich ganz gut. Wenn ich aber die Programme auf zwei Rechnern miteinander kommunizieren lassen möchte passiert nichts. Bei dem Rechner mit dem Client-Programm kommt nach einer gewissen Zeit die Fehlermeldung:

TimeoutError: WinError 10060 Ein Verbindungsversuch ist fehlgeschlagen, da die Gegenstelle nach einer bestimmten Zeitspanne nicht richtig reagiert hat, oder die hergestellte Verbindung war fehlerhaft, da der verbundene Host nicht reagiert hat.

Mir ist bewusst das dieses Thema sicher schon mehrere male durchgekaut wurde. Habe auch schon das Forum durchsucht um evtl. eine Idee zu finden. Oder habe ich da noch was übersehen was im Programm fehlt?

Die beiden Rechner befinden sich im gleichen Wlan.

Ich hoffe es kann mir jemand Hilfestellung geben oder einen Tipp was ich noch beachten muss.

Vielen Dank
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Pandorarain: das ist das Problem mit im Internet gefundenen Beispielen. Die sind bei Sockets zu 99% fehlerhaft. Zuerst brauchst Du ein Protokoll für die Datenübertragung. Hier kann es ein einfaches zeilenbasiertes Protokoll sein. Dann solltest Du Deinen Server an das richtige Gateway binden, das ist die Adresse über die Du kommunizieren willst. Normalerweise ist das 0.0.0.0 also irgendeine Adresse.

Das ganze könnte für den Server dann so aussehen:

Code: Alles auswählen

import socket
 
serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
print('waiting for client')
serversocket.bind(('0.0.0.0', 5000))
serversocket.listen(0)
 
(clientsocket, adress) = serversocket.accept()
print('client connected')

client = clientsocket.makefile('rw', encoding='UTF8')
for line in client:
    print(line)
    client.write('Server hat folgende Anfrage erhalten: '+ line)
    client.flush()
   
clientsocket.close()
serversocket.close()
Den Client kannst Du analog mit makefile umschreiben.
Pandorarain
User
Beiträge: 5
Registriert: Freitag 24. Februar 2017, 16:53

@Sirius3: Erstmal vielen Dank für die schnelle Antwort. Ich werde versuchen das umzusetzen. Aber ich muss ehrlich gestehen, ich weiss nicht wo ich anfangen soll und wie ich das umsetzen muss. Das mit dem Protokoll habe ich noch nicht ganz verstanden. Entspricht das dem von dir abgeänderten Code?

Wo finde ich evtl. weitere Informationen, wie ich das umsetzen kann?

Vielen Dank für die Hilfe.
BlackJack

@Pandorarain: Bezüglich des Protokolls: TCP-Socketverbindungen bieten einen Datenstrom. Wenn darüber strukturierte Daten gehen sollen, also beispielsweise mehrere, einzelne Nachrichten, dann muss man selbst dafür sorgen, dass man diese Nachrichten aus dem Datenstrom entsprechend aufteilt. Die Beschreibung wie solche Nachrichten aussehen, und wie man erkennt wann eine komplett ist, nennt man Protokoll. Oft wird da noch mehr festgelegt, zum Beispiel verschiedene Typen von Nachrichten und ihr interner Aufbau.

Das Protokoll das Sirius3 da jetzt umgesetzt hat ist ein sehr einfaches: Jede Nachricht ist eine Zeile die durch das Zeilenende-Zeichen beendet wird und der Inhalt der Zeile ist UTF-8 kodiert. Das bekommt man vom Dateiobjekt quasi gescheckt, weil man beim Erstellen die Kodierung angeben kann und weil Dateiobjekte iterierbar sind und dabei die Zeilen liefern.

Man könnte auch festlegen das alle Nachrichten gleich gross sein sollen. Oder das am Anfang von jeder Nachricht die Länge der Nachricht stehen muss. Oder auch Kombinationen davon. Bei HTTP gibt es beispielsweise bei Antworten üblicherweise eine Anzahl von Header-Zeilen, deren Anzahl variieren kann, und die werden mit einer Leerzeile beendet. In den Headerzeilen steht dann die Information wie viele Bytes nach der Leerzeile noch zur Nachricht gehören ('Content-Length:'-Header).

Informationen wie Du *was* umsetzen kannst? Erste Antwort ist in der Regel „Nicht selbst machen wenn es da schon etwas für gibt.“
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was soll's denn mal werden? Ich benutze inzwischen ja gerne nanomsg, man kann aber auch ZeroMQ nehmen. Diese Bibliotheken stellen Netzwerkverbindungen bereit, wie sie sein sollten. Zb Nachrichten-basiert, robust bei Verbindungsabbruechen oder Startreihenfolgen etc. Damit muss man sich um den roedeligen Kram nicht kuemmern.
Antworten