Weiß nicht ob man das als Modul posten sollte, könnt ihr ja umschreiben wenn ihr wollt.
Ein TCollectingStream ist ein TStream, der zum Versenden und Empfangen über Sockets gedacht ist. Er erinnert etwas an die BB-TCP/UDP-Streams. Anders als der "Socketstream" schickt er bei WriteByte etc. nicht ein Paket sofort los, sondern sammelt vorher alle Daten in einem array.
Umgekehrt gilt das gleiche: ein UDP-Socket möchte, anders als ein TCP-Socket dem das egal ist, alles Empfangene auf einen Schlag abgeben. Also buffert der CollectingStream auch die ankommenden Signale.
Nun aber zu den Funktionen und Methoden:
- Function Create:TCollectingStream(socket:TSocket,autoClose:Int=True)
Der Konstruktor. Er initialisiert den Stream für einen bestimmten Socket.
Ein TCP-Socket sollte entweder von SocketAccept kommen oder mit ConnectSocket verbunden worden sein.
Einen UDP-Socket kann man ohne Vorbereitung übergeben.
- Method Recv(sender:Int[]=Null)
Sieht nach neuen empfangbaren Daten und buffert diese.
Ist sender ein Int[2] wird die Absender-IP in sender[0] und der Absender-Port in sender[1] geschrieben.
Während bei TCP der Partner bekannt ist, kann man so den Absender einer UDP-Nachricht ermitteln.
- Method Eof:Int()
Überschreibt die Methode von TStream.
Ist -1 wenn der Socket nicht verbunden ist.
Ist 1 wenn der Lesebuffer leer ist.
Sonst gibt die Funktion 0 zurück.
- Method ReadAvail:Int()
Gibt socket.ReadAvail() zurück
- Method Close()
Schließt den Stream und falls autoClose=True ist auch den Socket.
- Method Send:Int(receiver:Int[]=Null)
Sendet die gebufferten Daten los. Ist ein reciever als Int[2] angegeben wird vorher der Socket connected mit der IP reciever[0] und dem Port reciever[1]. Das ist nützlich für UDP-Streams, bei denen der Empfänger ja nicht vorgegeben ist.
Alle anderen Methoden wurden von TStream geerbt und verhalten sich entsprechend und da der Type von TStream erbt, kann er überall da eingesetzt werden, wo ein TStream erwartet wird. Nur die Funktion die Sendet und Empfängt muss TCollectingStream wirklich kennen.
Hier nun der Code:
BlitzMax: [AUSKLAPPEN] [EINKLAPPEN] SuperStrict
Type TCollectingStream Extends TStream Function Create:TCollectingStream(socket:TSocket,autoClose:Int=True) Local this:TCollectingStream=New TCollectingStream this.socket=socket this.autoClose=autoClose Return this End Function
Field senda:Byte[]=New Byte[0] Field recva:Byte[]=New Byte[0] Field socket:TSocket,autoClose:Int Method Recv(sender:Int[]=Null) Local count:Int=socket.ReadAvail() Local buf:Byte[]=New Byte[count] If sender And sender.length>1 If recvfrom_(socket._socket,buf,count,0,sender[0],sender[1])<0 Throw "Unable to recieve data." EndIf Else If socket.recv(buf,count)=0 Throw "Unable to recieve data." EndIf EndIf recva=recva[..recva.length+count] For Local i:Int=recva.length-count To recva.length-1 recva[i]=buf[i-recva.length+count] Next End Method Method Eof:Int() If socket.Connected() If recva.length=0 Return True EndIf Else Return -True Else Return 0 End Method Method ReadAvail:Int() Return socket.ReadAvail() End Method Method Close() Super.Close() If autoClose Socket.Close() EndIf End Method Method Read:Int( buf:Byte Ptr,count:Int ) If count>recva.length For Local i:Int=0 To recva.length-1 buf[i]=recva[i] Next count=recva.length recva=New Byte[0] Else For Local i:Int=0 To count-1 buf[i]=recva[i] Next recva=recva[count..] EndIf Return count End Method Method Write:Int(buf:Byte Ptr,count:Int) Local start:Int=senda.length senda=senda[..senda.length+count] For Local i:Int=0 To count-1 senda[start+i]=buf[i] Next Return count End Method Method Send:Int(receiver:Int[]=Null) If reciever<>Null socket.connect(receiver[0],receiver[1]) EndIf Local res:Int=socket.Send(senda,senda.length) senda=New Byte[0] Return res End Method End Type
Ich bin natürlich für Vorschläge offen.
|