Lindawb 0 Posted February 6, 2022 Hello, I'm sending 2 types of data, one as data and other one as simple text message, now with help of good people I was able to get data as memorystream, but I can't get any string text Client.Send(aBuff,Length(aBuff)); // works on OnDataAvailable but Client.SendStr('This is a string'); // doesn't work, like bad header My question: is it possible to check the sent data(tbyes) or string, if winsocketdata process as data, if string just read it as string on same OnDataAvailable ? Thank you Share this post Link to post
Lajos Juhász 295 Posted February 6, 2022 You've to create a protocol eg. a prefix that will say the following x bytes is a string or a binary data so the reciever can convert the received bytes back. Share this post Link to post
qubits 20 Posted February 7, 2022 If you still sending your own packets, then strings need a header too, then converted to array of bytes just like the jpeg. added a send/recv string to the packet client and server demo, so you can see one way to do this. also generalized the server a bit, changed from q of jpeg to tPacketData which is DataType then array of bytes. Updated server example to show simple method of determining incoming array data. i tend to treat my strings as fixed arrays of bytes and those are in larger records of data. don't typically just send one string. i'll update the demo to show how to send record structures in a few days. Share this post Link to post
Angus Robertson 577 Posted February 7, 2022 As we explained previously, you need to design a protocol with a header to explain what type of data you are sending and how much. One well known such protocol is HTTP which ICS supports, and is much easier to use than designing your own. One standard in most protocols is that text is terminated with CRLF at the end of each command or line, which your SendStr does not do, but which can be useful to know that a complete line has arrived for processing and potentially to recognize that text is being sent, although binary files may potentially include CRLF. Angus Share this post Link to post
Lindawb 0 Posted February 7, 2022 Thank you all of you, Previously I did look all sockets demo, but I will check all demos to see how is done. I assume you are saying to do something like this: type TMyRec = record HeaderType: string; FirstName: string[40]; LastName: string[40]; Message: string; end; Thanks again for your time Share this post Link to post
Angus Robertson 577 Posted February 7, 2022 Your TMyRec would not work as a header since the String types point to memory and only the pointer would be sent, it needs fixed length elements and ideally Length: Integer at the start set to the actual length, so the application decoding it can handle changes in the record in the future. Angus Share this post Link to post
qubits 20 Posted February 7, 2022 No more like.. TMyRec = packed record Header:TPacketHdr; FirstName: array[0..39] of byte; LastName:array[0..39] of byte; Message:array[0..499] of byte; end; Share this post Link to post
qubits 20 Posted February 7, 2022 added this into the demo i did previously for you.. now you can send/recv a jpeg, a single string (can be as long as you wish) or a record structure. Share this post Link to post
Lindawb 0 Posted February 7, 2022 Thank you so much, I tried to use as below, but looks going nowhere. procedure TForm1.Button3Click(Sender: TObject); var defaultRec : TMyRec; result, mystr: string; aHdr:tPacketHdr; begin FillPacketIdent(aHdr.Ident); aHdr.Command:=CMD_STR; //CMD_STR added to uPacketDefs mystr:= 'Hello Delphi Developers'; aHdr.DataSize:=SizeOf(mystr[1]); // SetString(mystr, PAnsiChar(@defaultRec.FirstName[0]), Length(defaultRec.FirstName)); //write to record SetLength(mystr, length(defaultRec.FirstName)); Move(defaultRec.FirstName[0], mystr[1], Length(defaultRec.FirstName)); ShowMessage(PwideChar(defaultRec.FirstName[0])); // SetLength(result, Length(defaultRec.FirstName)); // Move(defaultRec.FirstName[0], result[1], Length(result) * SizeOf(result[1])); // SetLength(S, Length(A)); // Move(A[0], S[1], Length(S) * SizeOf(S[1])); //read the record SetString(result, pwidechar(@defaultRec.FirstName[0]), Length(defaultRec.FirstName)); ShowMessage(result); end; Thank you Share this post Link to post
qubits 20 Posted February 7, 2022 not usre how you got there, this is whats in the demo, i expanded the comments procedure TMainFrm.SendString; var aHdr:tPacketHdr; aStr:String; aBytes:TBytes; aBuff:TBytes; begin aStr:='Hello from client!!';//string could be sent into procedure if Length(aStr)>0 then begin FillPacketIdent(aHdr.Ident);//fill our indent aHdr.Command:=CMD_STR;//tell server its a string aBytes:=TEncoding.ANSI.GetBytes(aStr);//encode string to array of bytes SetLength(aBuff,SizeOf(tPacketHdr)+Length(aBytes));//make our transmission buffer big enough for header and string aHdr.DataSize:=Length(aBytes);// size of string, always use length instead of size of on dynamic sizes Move(aHdr,aBuff[0],SizeOf(tPacketHdr));// move the header into buffer Move(aBytes[0],aBuff[SizeOf(tPacketHdr)],Length(aBytes));//move string into buffer just after header PacketClntDm.cliSock.Send(aBuff,Length(aBuff));//send it off SetLength(aBytes,0); SetLength(aBuff,0); end; end; Share this post Link to post
Lindawb 0 Posted February 7, 2022 Thanks a trillion, worked like a charm! Share this post Link to post