3

I've been trying to set the length of the amount of characters you recover from the ReceiveText TClientSocket function and nothing seems to be working. E.g., Receiving the first leftmost character(s) from the recovered data or otherwise data stream. Is there a way to accomplish this in Delphi using this specific object?

Help would be much appreciated. Thanks in advance.

user1174509
  • 33
  • 1
  • 5
  • P.S- Maybe this pseudo-code will give someone a hypothetical insight as to what I'm specifically trying to achieve: `hClientSocket.Socket.ReceiveText(1);` – user1174509 Feb 08 '12 at 06:32
  • Welcome to StackOverflow. This site works a little different from newsgroups. You can edit questions, so you could have added your PS to the question instead of making it a comment. – Marjan Venema Feb 08 '12 at 09:52
  • Which Delphi version are you using? TClientSocket isn't installed by default in newer Delphi versions. – Jens Mühlenhoff Feb 08 '12 at 17:21
  • @JensMühlenhoff: I don't mean to be blunt or rather irrelevant, but who exactly said TClientSocket was installed by default in my Delphi distribution? Although oddly you guessed correctly; I'm not using a really recent version of Delphi— to be precise I'm using Delphi 7. However, just for the record, while the TClientSocket components may not be _installed_ by default, they're included somewhere in the installed files in Delphi 2009+ and can be installed manually accordingly. See [here](http://delphi.about.com/od/delphitips2008/qt/no_serverscoket.htm) for more information. – user1174509 Feb 08 '12 at 21:19
  • @MarjanVenema: Thank you for the welcoming. And yes, I'm fairly accustomed to how the StackOverflow system works. I included that message as a comment so it would be treated as a side-note rather than something directly pertaining to my question at hand so it wouldn't possibly obscure the actual question. – user1174509 Feb 08 '12 at 21:24
  • @user1174509 I did know that you can install TClientSocket in newer Delphi versions, I just wanted to point out that using it may not be the most future proof idea. – Jens Mühlenhoff Feb 09 '12 at 11:32

3 Answers3

1

here is a little tipp for sending and receiving text

first you must send the length of yout text too

Socket.SendText(IntToStr(Length(text)) + seperator + text);

then you can check at your server socket on receiving data streams, if your incoming text is complete

procedure TMyServer.OnClientRead(Sender: TObject; Socket: TCustomWinSocket);
begin
  if (xRecLength = 0) then begin
    if Length(Socket.ReceiveText) <= 0 then EXIT;
    xRecLength:= StrToIntDef(GetFirstFromSplitted(Socket.ReceiveText, seperator), -1);
    if xRecLength = -1 then EXIT;
  end;
  xActLength:= xActLength + Length(Socket.ReceiveText);
  xRecPuffer:= xRecPuffer + Socket.ReceiveText;

  isComplete:= xActLength = xRecLength;
  if isComplete then begin
    // complete text received
  end;
end;

hope that helps you...

punker76
  • 14,326
  • 5
  • 58
  • 96
  • Most if not all of that code is irrelevant to what I'm trying to do here. I could be mistaken though, but I doubt that by first glance. To clarify, I'm basically trying to specify the amount of characters I receive from the server (preferably via ReceiveText if that's doable). See my previous comment for an example. – user1174509 Feb 08 '12 at 08:19
  • @user1174509 you can use the first 4 bytes in the text that you're sending as holder for data-length OR everything before a character let's say dollar sign($) specifies the data length in bytes, so a typical message would look like "14$hello stranger" in case for AnsiString or "28$..." for WideString, but I would suggest moving to Indy, those are way better. –  Feb 08 '12 at 08:37
  • I've been contemplating on migrating to Indy's TCP client for some time now. One of the main reasons why I'm choosing to stick with TClientSocket for the meantime is basically simplicity. Also regarding your comment, could you elaborate? I have a profound understanding as to what you mean for the most part, however clarification would be nice. – user1174509 Feb 08 '12 at 08:58
  • Edit: Correct me if I'm wrong, but after examining your post a bit more thoroughly the question of how exactly would this apply to _recovering_ data rather when the basis of what you said is _sending_ it occurred to me. Further elaboration would be appreciated. – user1174509 Feb 08 '12 at 09:03
1

ReceiveText doesn't have any means to control the maximum length of the received text.

The easiest way in ClientType := ctBlocking mode is to use a TWinSocketStream as the documentation states:

http://docwiki.embarcadero.com/VCL/XE2/en/ScktComp.TClientSocket.ClientType

When ClientType is ctBlocking, use a TWinSocketStream object for reading and writing. TWinSocketStream prevents the application from hanging indefinitely if a problem occurs while reading or writing. It also can wait for the socket connection to indicate its readiness for reading.

Example code:

var
  Stream : TWinSocketStream;
  Buffer : TBytes;
  S      : string;
begin
  SetLength(Buffer, 100); // 100 bytes buffer size
  Stream := TWinSocketStream.Create(Socket, 5000); // 5 seconds or 5000 milliseconds
  try
    Stream.ReadBuffer(Buffer[0], Length(Buffer)); // raises an Exception if it couldn't read the number of bytes requested
    S := TEncoding.Default.GetString(Buffer); // Works in Delphi 2009+
  finally
    Stream.Free;
  end;
end;
Jens Mühlenhoff
  • 14,565
  • 6
  • 56
  • 113
  • +1 - Personally I think this was the best answer yet. Straightforward and direct as to what I'm meaning to accomplish. However, the `TEncoding.Default.GetString` peaked my attention. I'm not using Delphi 2009+ so if there's an alternative to this what would be the implementation in a version like (Borland) Delphi 7.x? **Edit:** Aw, insufficient credentials. Can't vote-up you unfortunately. But I've taken the liberty of flagging this as my accepted answer. – user1174509 Feb 08 '12 at 21:11
  • Scratch that; I've got it going. Thanks again for the pointers. – user1174509 Feb 09 '12 at 00:20
  • I've upvoted your question now, that should give your reputation on SO a start and btw: Welcome to SO :) – Jens Mühlenhoff Feb 09 '12 at 11:13
0

I'm not at home with Delphi, but a quick Google search turned up this page that indicates that ReceiveText does not accept any parameters, but instead returns a string of as much as it can read.

What you might need is might be ReceiveBuf instead.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Thank you for your answer. And yes, I'm aware that `ReceiveText` does not accept arguments. It was an example meant to denote what I'm trying to accomplish (the ReceiveText method returning data character by character). Also, I've tried `ReceiveBuf` at one point and had no success with it. Mind providing an example of how to accomplish the aforementioned task via that route? – user1174509 Feb 08 '12 at 07:41
  • 1
    Additionally, after reviewing over the documentation you referenced, the underlying issue with `ReceiveBuf` may have to do with the fact that I'm using blocking sockets as opposed to non-blocking sockets. Utilizing the `TWinSocketStream` object seems to be the only feasible approach to the situation at this point. However, accomplishing the same task in a language like Python via the usage of its standard library `socket` you can achieve this simply by passing data to the `recv` function parameter (I.e. socket.recv(BUFFER_SIZE). – user1174509 Feb 08 '12 at 07:55
  • @user1174509 I suggest you put that comment as an answer to your own question. :) – Some programmer dude Feb 08 '12 at 08:00
  • Yeah, I know that this may be the solution to my problem in question, however my attempts at implementing the approaches I theorize have failed thus far. So, as such I'm looking for a more concrete answer to my question possibly demonstrated by means of code distribution. – user1174509 Feb 08 '12 at 08:14