Recent

Author Topic: Assign a File using a File Descriptor  (Read 583 times)

MMarie

  • New Member
  • *
  • Posts: 27
  • Right, lets bodge this pisspot
    • Homepage
Assign a File using a File Descriptor
« on: December 09, 2022, 07:42:58 am »
Im currently working on a Simple TCP-Server and I'm trying to just get the example to work using fpAccept instead of the deprecated Accept. fpAccept returns a File-Descriptor on success, but I can't find anything on how to use this File-Descriptor to read and write to/from the socket.

Here is my source code. (I know that I will get an In- Out- Error because Sin and Sout aren't assigned)
Code: Pascal  [Select][+][-]
  1. {$mode fpc}
  2. program bugattiserv;
  3.  
  4. uses CTypes, SysUtils, Sockets, UnixType;
  5.  
  6. var
  7.   FromName   : pSockAddr;
  8.   FromNameLen: pSockLen;
  9.   Buffer     : string[255];
  10.   S          : Longint;
  11.   SockFile   : CInt;
  12.   Sin,Sout   : Text;
  13.   SAddr      : TInetSockAddr;
  14.  
  15. procedure perror(const S:string);
  16. begin
  17.   writeln (S,SocketError);
  18.   halt(100);
  19. end;
  20.  
  21. begin
  22.   S:=fpSocket (AF_INET,SOCK_STREAM,0);
  23.   if SocketError<>0 then
  24.     Perror ('Server : Socket : ');
  25.  
  26.   SAddr.sin_family:=AF_INET;
  27.  
  28.   SAddr.sin_port:=htons(5000);
  29.   SAddr.sin_addr.s_addr:=0;
  30.   if fpBind(S,@SAddr,sizeof(saddr))=-1 then
  31.     PError ('Server : Bind : ');
  32.   if fpListen (S,1)=-1 then
  33.     PError ('Server : Listen : ');
  34.  
  35.   Writeln('Waiting for Connect from Client, run now sock_cli in an other tty');
  36.   SockFile := fpAccept(S,FromName,FromNameLen);
  37.   if SockFile = -1 then
  38.     PError ('Server : Accept : '); // + IntToStr(FromName^.sin_addr.in_addr));
  39.  
  40.   Reset(Sin);
  41.   ReWrite(Sout);
  42.   Writeln(Sout,'Message From Server');
  43.   Flush(SOut);
  44.   while not eof(sin) do
  45.   begin
  46.     Readln(Sin,Buffer);
  47.     Writeln('Server : read : ',buffer);
  48.   end;
  49. end.
  50.  
  51.  
i use arch btw

dje

  • Full Member
  • ***
  • Posts: 134
Re: Assign a File using a File Descriptor
« Reply #1 on: December 09, 2022, 08:52:19 am »
I would assume you are after fprecv and fpsend

https://www.freepascal.org/docs-html/rtl/sockets/fpsend.html
https://www.freepascal.org/docs-html/rtl/sockets/fprecv.html

EDIT:
There is also TSocketStream which adapts the socket handle to a TStream object. You could then try to Assign that to a TextFile via AssignStream in the unit StreamIO

That should allow you to use standard Pascal Read/Write functions, but, I'm sure others will recommend you stick with fprecv & fpsend
« Last Edit: December 09, 2022, 09:03:48 am by dje »

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Assign a File using a File Descriptor
« Reply #2 on: December 09, 2022, 09:18:16 am »
DO NOT put something as important as the OS (and FPC version etc.) in your sig. As soon as you change your sig messages that you have already posted will be changed to track it, and in any event it does not show up when somebody tries to quote important context from your message- as I've just done.

You're using Arch. Fine, that's Linux. So it's the standard sockets API, and whataver the docs like to call it fpaccept() returns a standard handle (clue: it's an integer rather than a data structure).

Go to the documentation https://www.freepascal.org/docs.html Go to RTL, Sockets unit... if you can't be bothered to scroll down there's an index link at the top. Go to Procedures and Functions hence fpaccept(). Make a note of the URL and raise a bug report against it, since the example refers to Accept() rather than fpaccept().

(Gawd, now you've got me felling grumpy about somebody else :-)

The basic problem is that the Accept() in that example is for associating standard Pascal textfiles with a socket, which might or might not be properly supported by current fpaccept() (I went through this from a different angle a few months ago, and somebody explained the detail).

This is from something recently worked on:

Code: Pascal  [Select][+][-]
  1.                   fClient := fpAccept(fSocket, @sockAddr, @sockLen); (* Blocking call *)
  2. ...
  3.       while true do begin
  4.         if fpRecv(fClient, @c, 1, 0) < 1 then
  5.           exit(-1);
  6.         if not (c in ['0'..'9']) then
  7.           break;
  8. //        fpSend(fClient, @star[1], 1, 0);
  9.         s += c
  10.       end;
  11.  

That's a very small part of a Telnet server, showing the bit that accepts the connection plus a simple reader for a PIN from the client connecting. The fpsend() to echo stars was removed since it turned out to be more problem than it was worth, but I've left it in as an example to demonstrate that this is all standard Berkeley Sockets stuff.

Slightly later: The older relevant thread is https://forum.lazarus.freepascal.org/index.php/topic,57706.0.html However unless you have a very good reason I would suggest sticking to the standard sockets API with the thin wrappers provided by the RTL, i.e. use fpsend() etc. rather than Write().

I've also recently been looking at intercepting the standard textfile devices so that a program can redirect its input and output textfiles via Telnet (i.e. act as a Telnet server) for debugging purposes. Discussion at https://forum.lazarus.freepascal.org/index.php/topic,61418.0.html and I'll be posting it on Github presently.

MarkMLl
« Last Edit: December 09, 2022, 09:40:28 am by MarkMLl »
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

MMarie

  • New Member
  • *
  • Posts: 27
  • Right, lets bodge this pisspot
    • Homepage
Re: Assign a File using a File Descriptor
« Reply #3 on: December 09, 2022, 11:06:59 am »
DO NOT put something as important as the OS (and FPC version etc.) in your sig. As soon as you change your sig messages that you have already posted will be changed to track it, and in any event it does not show up when somebody tries to quote important context from your message- as I've just done.

You're using Arch. Fine, that's Linux. So it's the standard sockets API, and whataver the docs like to call it fpaccept() returns a standard handle (clue: it's an integer rather than a data structure).

Go to the documentation https://www.freepascal.org/docs.html Go to RTL, Sockets unit... if you can't be bothered to scroll down there's an index link at the top. Go to Procedures and Functions hence fpaccept(). Make a note of the URL and raise a bug report against it, since the example refers to Accept() rather than fpaccept().

(Gawd, now you've got me felling grumpy about somebody else :-)

The basic problem is that the Accept() in that example is for associating standard Pascal textfiles with a socket, which might or might not be properly supported by current fpaccept() (I went through this from a different angle a few months ago, and somebody explained the detail).

This is from something recently worked on:

Code: Pascal  [Select][+][-]
  1.                   fClient := fpAccept(fSocket, @sockAddr, @sockLen); (* Blocking call *)
  2. ...
  3.       while true do begin
  4.         if fpRecv(fClient, @c, 1, 0) < 1 then
  5.           exit(-1);
  6.         if not (c in ['0'..'9']) then
  7.           break;
  8. //        fpSend(fClient, @star[1], 1, 0);
  9.         s += c
  10.       end;
  11.  

That's a very small part of a Telnet server, showing the bit that accepts the connection plus a simple reader for a PIN from the client connecting. The fpsend() to echo stars was removed since it turned out to be more problem than it was worth, but I've left it in as an example to demonstrate that this is all standard Berkeley Sockets stuff.

Slightly later: The older relevant thread is https://forum.lazarus.freepascal.org/index.php/topic,57706.0.html However unless you have a very good reason I would suggest sticking to the standard sockets API with the thin wrappers provided by the RTL, i.e. use fpsend() etc. rather than Write().

I've also recently been looking at intercepting the standard textfile devices so that a program can redirect its input and output textfiles via Telnet (i.e. act as a Telnet server) for debugging purposes. Discussion at https://forum.lazarus.freepascal.org/index.php/topic,61418.0.html and I'll be posting it on Github presently.

MarkMLl

Thanks for the great example and insight! I've filed a bug report over on GitLab.
i use arch btw

MarkMLl

  • Hero Member
  • *****
  • Posts: 6676
Re: Assign a File using a File Descriptor
« Reply #4 on: December 09, 2022, 11:27:33 am »
Well done. Sorry about being a grouch earlier, but I almost overlooked your message due to the "descriptor" business... I assumed you were using Windows or something.

I think the important thing is that most major OSes have settled on a convention where at the lowest level an open file (or socket etc.) is indicated by an integer. This is usually small- i.e. a handle- but in some cases might be a pointer which should be treated as opaque (but which points to something which might be called a descriptor).

On top of that- in the Pascal case- you've got the old textfiles which basically have a legacy going back to punched cards, typed files (i.e. "file of" etc.), and streams. Most people seem to favour streams these days but quite frankly I feel that they introduce a layer of cruft that I very rarely need.

But the fpSend(), fpWrite() and so on functions work with handles, and it's always worth understanding what's going on there even if later you decide to use one of the prepackaged component sets. So I regularly find myself going direct to a socket to handle UDP or non-standard TCP protocols, but I wouldn't dream of it if I needed to do something with SSL (i.e. an https:// connection etc.) or talk to a mail server.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

 

TinyPortal © 2005-2018