Proces wysyłania i odbierania wiadomości różni się między standardami TCP i WebSocket. Poniżej szczegółowo wyjaśniamy ten proces dla obu typów połączeń.
Aby wysłać wiadomość przez połączenie TCP, wykonaj następujące czynności:
Zmień wiadomość Protobuf na tablicę bajtów (używając kodowania Protobuf) przy użyciu oficjalnego SDK Google Protocol Buffer dla wybranego języka programowania.
Pobierz długość tablicy utworzonej podczas kroku 1. Utwórz nową tablicę bajtów z tej liczby całkowitej. Odwróć nową tablicę bajtów.
Połącz nową tablicę bajtów i tablicę bajtów zawierającą oryginalną wiadomość Protobuf.
Wyślij połączoną tablicę do strumienia połączenia.
Poniższe przykłady pokazują, jak te kroki są wykonywane w oficjalnych SDK Open API.
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)
Przykład Python
Używając Twisted, przykład Python wykonuje niemal te same operacje co przykład C#. client.send(request) można wyjaśnić w następujący sposób.
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
Do wysyłania wiadomości SDK Python używa metody Protocol.transport.write().
Wszystkie SDK Open API opierają się na wykonywaniu asynchronicznym, co oznacza, że nie czekają na nadejście wiadomości, ale zamiast tego reagują na dynamicznie przychodzące wiadomości. W rezultacie odbieranie wiadomości odbywa się zazwyczaj za pośrednictwem procedur obsługi zdarzeń
Aby odczytać wiadomość, będziesz musiał wykonać sekwencję działań, która odwraca kroki wymagane do wysłania wiadomości.
Odbierz pierwsze cztery bajty tablicy bajtów (pamiętaj, oznaczają one długość wiadomości). Odwróć te cztery bajty i zmień je na liczbę całkowitą.
Odczytaj X bajtów ze strumienia, gdzie X to liczba całkowita, którą otrzymałeś podczas kroku 1.
Użyj SDK Google Protobuf, aby zdeserializować wiadomość do prawidłowej ProtoMessage.
Użyj pola payloadType obiektu ProtoMessage, aby znaleźć jego rzeczywisty typ. Za pomocą Google Protobuf SDK zmień ProtoMessage na obiekt wymaganego typu ProtoOA....
Poniższe fragmenty kodu pokazują, jak oficjalne SDK Open API odczytują wiadomości.
_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);}
Przykład w Pythonie
W przykładzie w Pythonie wszystkie operacje na bajtach podczas odbierania wiadomości są obsługiwane przez metodę dataReceived(), jak pokazano poniżej.
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)
Aby wysłać wiadomość przez połączenie WebSocket, wykonaj następujące czynności:
Serializuj wiadomość do dowolnego odpowiedniego formatu danych (na przykład ciągu znaków).
Dodaj serializowaną wiadomość do kolejki wysyłania.
Poniższe przykłady pokazują, jak te czynności są wykonywane w oficjalnych SDK Open API.
SDK C# używa klasy WebsocketClient, która jest częścią pakietu Websocket.Client. Jak pokazano poniżej, metoda WebsocketClient.Send() działa w następujący sposób.
Przed subskrypcją SDK .NET analizuje wiadomość na wiadomość Protobuf. Niezbędne subskrypcje są dodawane w treści wywołania zwrotnego ConnectWebSocket().