Der Prozess des Sendens und Empfangens einer Nachricht unterscheidet sich zwischen den TCP- und WebSocket-Standards. Im Folgenden erklären wir diesen Prozess ausführlich für beide Verbindungstypen.
Um eine Nachricht über eine TCP-Verbindung zu senden, gehen Sie wie folgt vor:
Ändern Sie die Protobuf-Nachricht in ein Byte-Array (mithilfe der Protobuf-Codierung), indem Sie das offizielle Google Protocol Buffer SDK für Ihre gewählte Programmiersprache verwenden.
Ermitteln Sie die Länge des in Schritt 1 erstellten Arrays. Erstellen Sie aus dieser Ganzzahl ein neues Byte-Array. Kehren Sie das neue Byte-Array um.
Verketten Sie das neue Byte-Array und das Byte-Array, das die ursprüngliche Protobuf-Nachricht enthält.
Senden Sie das verkettete Array an den Verbindungsstream.
Die folgenden Beispiele zeigen, wie diese Schritte in den offiziellen Open API SDKs ausgeführt werden.
client=Client(EndPoints.PROTOBUF_LIVE_HOSTifhostType.lower()=="live"elseEndPoints.PROTOBUF_DEMO_HOST,EndPoints.PROTOBUF_PORT,TcpProtocol)request=ProtoOAApplicationAuthReq()# Can be any messagedeferred=client.send(request)
Python-Beispiel
Mithilfe von Twisted führt das Python-Beispiel nahezu dieselben Vorgänge wie das C#-Beispiel aus. Das client.send(request) kann wie folgt erklärt werden.
123
request=ProtoOAApplicationAuthReq()# Can be any messagerequestAsString=request.SerializeToString()# This method is a part of the Google Protobuf SDKrequestAsInt32String=struct.pack("!H",len(requestAsString))# The message is concatenated with the reversed array
Zum Senden der Nachricht verwendet das Python SDK die Methode Protocol.transport.write().
Alle Open API SDKs basieren auf asynchroner Ausführung, d. h., sie warten nicht auf eingehende Nachrichten, sondern reagieren stattdessen auf dynamisch eintreffende Nachrichten. Daher erfolgt der Empfang einer Nachricht in der Regel über Ereignishandler
Um eine Nachricht zu lesen, müssen Sie eine Abfolge von Aktionen ausführen, die die zum Senden einer Nachricht erforderlichen Schritte umkehrt.
Empfangen Sie die ersten vier Bytes eines Byte-Arrays (denken Sie daran, dass sie die Nachrichtenlänge angeben). Kehren Sie diese vier Bytes um und ändern Sie sie in eine Ganzzahl.
Lesen Sie X Bytes aus einem Stream, wobei X die Ganzzahl ist, die Sie in Schritt 1 erhalten haben.
Verwenden Sie das Google Protobuf SDK, um die Nachricht in eine gültige ProtoMessage zu deserialisieren.
Verwenden Sie das Feld payloadType des Objekts ProtoMessage, um dessen tatsächlichen Typ zu ermitteln. Ändern Sie über das Google Protobuf SDK die ProtoMessage in ein Objekt des benötigten Typs ProtoOA....
Die folgenden Codeausschnitte zeigen, wie die offiziellen Open API SDKs das Lesen von Nachrichten handhaben.
_tcpClient=newTcpClient{LingerState=newLingerOption(enable:true,10)};await_tcpClient.ConnectAsync(Host,Port).ConfigureAwait(continueOnCapturedContext:false);SslStream_sslStream=newSslStream(_tcpClient.GetStream(),leaveInnerStreamOpen:false);await_sslStream.AuthenticateAsClientAsync(Host).ConfigureAwait(continueOnCapturedContext:false);privateasyncvoidReadTcp(CancellationTokencancellationToken){byte[]dataLength=newbyte[4];byte[]data=null;try{while(!IsDisposed){intnum=0;do{intcount=dataLength.Length-num;intnum2=num;num=num2+await_sslStream.ReadAsync(dataLength,num,count,cancellationToken).ConfigureAwait(continueOnCapturedContext:false);if(num==0){thrownewInvalidOperationException("Remote host closed the connection");}}while(num<dataLength.Length);intlength=GetLength(dataLength);if(length<=0){continue;}data=ArrayPool<byte>.Shared.Rent(length);num=0;do{intcount2=length-num;intnum2=num;num=num2+await_sslStream.ReadAsync(data,num,count2,cancellationToken).ConfigureAwait(continueOnCapturedContext:false);if(num==0){thrownewInvalidOperationException("Remote host closed the connection");}}while(num<length);ProtoMessageprotoMessage=ProtoMessage.Parser.ParseFrom(data,0,length);ArrayPool<byte>.Shared.Return(data);OnNext(protoMessage);}}catch(ExceptioninnerException){if(data!=null){ArrayPool<byte>.Shared.Return(data);}ReceiveExceptionexception=newReceiveException(innerException);OnError(exception);}}privateintGetLength(byte[]lengthBytes){Span<byte>span=lengthBytes.AsSpan();span.Reverse();returnBitConverter.ToInt32(span);}
Python-Beispiel
Im Python-Beispiel werden alle Vorgänge mit Bytes beim Empfangen von Nachrichten von der Methode dataReceived() verarbeitet, wie unten gezeigt.
1 2 3 4 5 6 7 8 910111213141516
defdataReceived(self,recd):""" Convert int prefixed strings into calls to stringReceived. """self.recvd=self.recvd+recdwhilelen(self.recvd)>=self.prefixLengthandnotself.paused:length,=struct.unpack(self.structFormat,self.recvd[:self.prefixLength])iflength>self.MAX_LENGTH:self.lengthLimitExceeded(length)returniflen(self.recvd)<length+self.prefixLength:breakpacket=self.recvd[self.prefixLength:length+self.prefixLength]self.recvd=self.recvd[length+self.prefixLength:]self.stringReceived(packet)
Um eine Nachricht über eine WebSocket-Verbindung zu senden, führen Sie die folgenden Aktionen aus:
Serialisieren Sie die Nachricht in ein beliebiges geeignetes Datenformat (z. B. eine Zeichenfolge).
Fügen Sie die serialisierte Nachricht Ihrer Sendewarteschlange hinzu.
Die folgenden Beispiele zeigen, wie diese Aktionen in den offiziellen Open API SDKs ausgeführt werden.
Das C# SDK verwendet die Klasse WebsocketClient, die Teil des Pakets Websocket.Client ist. Wie unten gezeigt, funktioniert die Methode WebsocketClient.Send() wie folgt.
Um eine Nachricht über eine WebSocket-Verbindung zu empfangen, gehen Sie wie folgt vor:
Rufen Sie die vom cTrader-Backend empfangenen Daten ab.
Deserialisieren Sie die Daten in eine gültige Protobuf-Nachricht.
Eine Veranschaulichung, wie dies in den offiziellen Open API SDKs erfolgt, finden Sie in den folgenden Ausschnitten.
Um Nachrichten zu empfangen, muss ein WebsocketClient eine Rückruffunktion abonnieren, die festlegt, was der Client beim Akzeptieren einer neuen Nachricht tut.
Vor dem Abonnieren analysiert das .NET SDK die Nachricht in eine Protobuf-Nachricht. Die erforderlichen Abonnements werden im Hauptteil des Rückrufs ConnectWebSocket() hinzugefügt.