TCP Chat Hilfe/Tipps

06/01/2014 18:05 ruffnirs#1
Hi, ich hoffe das gehört hier hin :confused:

Ich habe damit angefangen mich mit Autoit auseinander zu setzen und einen "Chat" wenn man es so nennen will geschrieben. Ich habe das Gefühl dass ich es sehr umständlich und nicht so geschrieben habe wie man das vielleicht machen sollte. Ich fände es ziemlich cool von euch wenn ihr mir helfen könntet wie ich das ganze "professioneller" aufbauen kann. Ich habe vor Autoit richtig zu lernen und nicht nur Spaghetticode zu produzieren.
Alles was ihr mir an Tipps gebt nehme ich gerne an :)

Ich hoffe das ist nicht zu ungenau.. ich bin kein totaler Anfänger auf dem Gebiet aber eben mit Autoit.

Vielen Dank schon mal

Server:

Client



EDIT _______________________ Die Scripte so dass sie laufen _____________________________

Ein kleiner Chat (klappt über eine Lan bzw. W-Lan Verbindung problemlos, online wurde er noch nicht getestet)

Server:

Client
06/01/2014 18:47 alpines#2
Ich hab mich mit deiner Problematik nicht ganz befasst, allerdings kannst du bei der _getMsg Funktion etwas korrigeren.
Sende deine Nachrichten am Ende immer mit einem Zeichen das einzigartig ist, damit du solange in den Buffer receiven kannst bis dieses Zeichen angekommen ist.
So vermeidest du Datenverlust.

Des Weiteren solltest du alle Handles von TCP-Verbindungen schließen wenn du das Programm beendest.

Außerdem speicherst du Werte ein die du nur tatsächlich einmal benötigst, unnötige Variablen zu erstellen zieht an der Performance.
Ein Beispiel ist der Teil beim Clienten mit $sendedBytes = ...
und If $sendedBytes...
Warum machst du daraus nicht direkt
Code:
If Not TCPSend($socket, $msg) Then MsgBox ;...
06/02/2014 10:55 ruffnirs#3
Vielen Dank, mit den Variablen ist logisch habe ich einfach unnötig Code.
Hast du bei dem _getMsg Funktion ein Link für mich der das genauer erklärt?
Ich dachte bei TCP ist das mit dem Datenverlust nicht so relevant wie bei UDP.

Verbindungen schließen ist auch logisch.
06/02/2014 11:46 alpines#4
Generell würde ich dir erstmal raten die ungarische Notation dir anzugewöhnen, klar bei typenunspezifischen Sprachen wie AutoIt braucht man das nicht direkt aber es hilft trotzdem.

So könnte aus $ipClient $sIpClient werden (s = String) und aus $StartButton $hStart oder $btnStart.
Der Präfix hilft dir bei größeren Projekten dabei was in der Variable enthalten ist.

Das mit dem Zeichen am Ende ist ganz einfach.
Client sendet als Beispiel:
Code:
StringReplace("Hallo, das ist ein Text!", Chr(0), "") & Chr(0)
Dabei ist Chr(0) das Zeichen was eine Nachricht erfolgreich abschließt.
In der Nachricht selbst werden alle Chr(0) zur Sicherheit entfernt.
Der Server hat dann das hier als Schleife
Code:
$sBuffer = "" ;Buffer vor jedem receiven clearen.

Do
	$sBuffer &= TCPRecv($hSocket, 2048)
Until StringTrimLeft($sBuffer, StringLen($sBuffer) - 1) = Chr(0)
Der Grund warum man ein speziellen Char am Ende haben sollte ist z.B. bei HTTP-Packets.
Dort werden viele kB gesendet und mit einem receiven kommt man da nicht weit, d.h. lieber solange dort receiven bis man ein </html> z.B. hat.
06/02/2014 12:41 ruffnirs#5
Ist es eigentlich nötig die IP des Clienten zu kennen um eine Nachricht vom Server an den Clienten zu schicken oder kann man die aus der Verbindung Server -> Client herleiten? In meinem Fall muss ich diese ja Manuell eintragen.
Also ich habe mir überlegt es nach diesem Modell umzuschreiben:

Client "Hallo Server hier bin ich das ist meine IP"
Server"Hallo Client ich kann jetzt mit dir Kommunizieren"

Muss ich das so machen oder kann ich aus dem Socket die IP des Clienten auslesen? Oder nur die des Servers?

Ist der Buffer in diesem Fall nicht eine "Unnötige Variable" ? Würde das nicht

Code:
 
Do 
   TCTRecv($hSocket, 2048)  ; Warum eigentlich 2048 Zeichen? 
Until StringTrimLeft (TCPRecv ($hSocket, 2048), StringLen(TCPRecv ($hSocket, 2048) -1 ) = Chr(0)
den gleichen Effekt haben? Also was bringt mir der Buffer?

Ich bin auch für jeden Link mit Erklärungen zu den Verfahren bzw. Funktionen dankbar.
Die Autoit Hilfe bietet da leider nur eine sehr oberflächliche Erklärung.
06/02/2014 13:05 alpines#6
In der Hilfe gibt es zu TCPRecv glaube ich eine Funktion namens SocketToIp die den Socket von TCPAccept zu einer IP umwandelt.
Da muss der Client keine IP mitschicken, wäre ja Schwachsinn.

Falsch, es hätte nicht den selben Effekt.
Wenn du die erste Hälfte z.B. abrufst wird sie aus dem Buffer gelöscht, deshalb das $sBuffer &= TCPRecv($hSocket, 2048)

2048 Zeichen sind nur random gewählt, kannst auch jede andere Zahl nehmen.
06/02/2014 14:01 ruffnirs#7
Das heißt ich könnte hier bei case $StartButton ff. auch einfach statt TCPConnect usw. die $socket Variable benutzen die ich die ganze Zeit sowieso schon nutze, also die die ich von TCPAccept zurück bekomme? Wenn der Client dann aber nicht in dem Moment sendet ist die Variable doch leer? wie könnte ich das lösen?
Code:
 
While 1


	$socket = TCPAccept($socketalt) ; verbindung mit client wird hergestellt


	Switch GUIGetMsg()				; GUI Actions
		Case	$StartButton
					$socket1=TCPConnect($ipClient,$port)
					$x=TCPSend($socket1,GUICtrlRead($InputLabel))
		Case $GUI_EVENT_CLOSE
					TCPCloseSocket($socket1)
					TCPShutdown()
					ExitLoop
	EndSwitch
	_getMsg()
WEnd

Edit ____

Hab das ganze mal versucht umzusetzen. Die Funktion SocketToip habe ich aus der Hilfe übernommen liefert aber immer den wert 0 zurück..

Hier müsste irgendwo der Denkfehler liegen. Vom Client kann ich Daten Empfangen der "$iSocket" ist auch nicht leer aber die Funktion liefert 0, was mach ich falsch?

Code:
$iSocket = TCPAccept($iSocketalt) ; verbindung mit client wird hergestellt
	if $iSocket <> -1 then
		ConsoleWrite("iSocket = "&$iSocket &@CRLF)
		$ipClient= _SocketToIP($iSocket)	; aus bestehender Verbindung mit Client die Ip des Clienten erfassen
		ConsoleWrite("Clientip = "&$ipClient&@CRLF)
	EndIf
Quellcode Server
06/02/2014 17:59 alpines#8
Ich denke du hast einen kleinen Denkfehler drinne, was du versuchst ist glaube ich eine Message vom Clienten zu receiven und dann zu ihm zu connecten um ihm was zu senden.

Das kannst du aber über den selben Socket machen, wenn du als Server von einem Clienten über den Socket $hConnectedSocket z.B. was receivest kannst du auch TCPSend($hConnectedSocket, $sMsg) machen.
06/02/2014 18:10 ruffnirs#9

dann müsste es aber doch so funktionieren und das tut es nicht.
Ich glaube weil ich bei _getMsg den Socket schon schließe wenn ich ihn da offen lasse geht es aber auch nicht.
06/02/2014 18:43 alpines#10
Den Socket von einem Clienten nicht schließen wenn er weitere Nachrichten senden möchte, lass den offen und prüfe ob neue Daten reinkommen.
06/02/2014 20:23 ruffnirs#11
So läuft alles :handsdown:
Ein kleiner Chat (klappt über eine Lan bzw. W-Lan Verbindung problemlos, online wurde er noch nicht getestet)

Server:

Client
06/02/2014 21:21 alpines#12
So, jetzt erstmal optimieren.
06/03/2014 12:19 ruffnirs#13
Vorschläge?
06/03/2014 12:32 alpines#14
Ja.
und das war gerade mal nur der Server...
Da kann man noch viel mehr optimieren.
06/03/2014 12:41 ruffnirs#15
Optimieren im welchen Sinne? Also erweitern ausbauen oder mögliche Buggs beheben oder was meinst du?