* TCP/IP Sockets with GNAT.Sockets @ 2005-05-02 2:42 fabio de francesco 2005-05-02 5:58 ` Eric Jacoboni 2005-05-02 12:11 ` Adrien Plisson 0 siblings, 2 replies; 23+ messages in thread From: fabio de francesco @ 2005-05-02 2:42 UTC (permalink / raw) Hello, Today is the first time I try to use sockets in Ada programs, even if I have some practical knowledge of programming with TCP/IP sockets in C. Because I didn't find any better tutorial on working with GNAT.Sockets I am relying on comments in file g-socket.ads from GCC/GNAT sources where there is not a complete and detailed coverage of the subject. (1) Do you know any better tutorial? Then I wrote two little programs in order to try the package. A server waits for connections and a client sends a string and receive an echo from the first one. The client can also shutdown the server by sending a predefined string. I hadn't too many problems with exchanging messages and everything works. The problem is that I was only able to use Streams for communicating between them and I can't understand at all how to use Receive_Socket() and Send_Socket() because they use "Stream_Element_Array" and "Stream_Element _Offset" in place of Strings. I know that by using Streams they can't communicate with C programs and I've read that Streams are everything but efficient. (2) The following is an extract from the client program. It compiles and works as it is. May you please explain how to modify it in order to use the above-mentioned functions in place of Input() and Output()? If the problem can be solved by copying Strings to Stream_Element_Array and back, how can I do that? -- file client.adb with GNAT.Sockets, Ada.Text_IO, Ada.Strings.Unbounded, Ada.Command_Line; use GNAT.Sockets, Ada.Text_IO, Ada.Strings.Unbounded, Ada.Command_Line; procedure Client is Socket : Socket_Type; Address : Sock_Addr_Type; Channel : Stream_Access; Reply : Unbounded_String; begin Initialize; Create_Socket( Socket ); Address.Addr := Inet_Addr( "127.0.0.1" ); Address.Port := 9876; Connect_Socket( Socket, Address ); Channel := Stream( Socket ); if Argument_Count > 0 then if Argument(1) = "kill" then Put_Line( "asking server to shutdown" ); String'Output( Channel, "kill" ); else Put_Line( "sending """ & Argument( 1 ) & """" ); String'Output( Channel, Argument( 1 ) ); end if; Reply := Unbounded_String'Input( Channel ); Put_Line( "server echos """ & To_String( Reply ) & """" ); end if; Free( Channel ); Close_Socket( Socket ); Finalize; end Client; -- end of client.adb Thanks to all of you who will reply. fabio de francesco ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 2:42 TCP/IP Sockets with GNAT.Sockets fabio de francesco @ 2005-05-02 5:58 ` Eric Jacoboni 2005-05-02 12:11 ` Adrien Plisson 1 sibling, 0 replies; 23+ messages in thread From: Eric Jacoboni @ 2005-05-02 5:58 UTC (permalink / raw) In article <1115001752.291144.218410@z14g2000cwz.googlegroups.com>, fabio de francesco <fmdf@tiscali.it> wrote: > I hadn't too many problems with exchanging messages and everything > works. The problem is that I was only able to use Streams for > communicating between them and I can't understand at all how to use > Receive_Socket() and Send_Socket() because they use > "Stream_Element_Array" and "Stream_Element _Offset" in place of > Strings. I know that by using Streams they can't communicate with C > programs and I've read that Streams are everything but efficient. Streams are ok if you manage both the server and the client program. Otherwise, for talking to a server already written, send and receive are ok. > (2) The following is an extract from the client program. It compiles > and works as it is. May you please explain how to modify it in order to > use the above-mentioned functions in place of Input() and Output()? If > the problem can be solved by copying Strings to Stream_Element_Array > and back, how can I do that? Here is a simple test code that use send/receive to talk to a POP3 server : with Gnat.Sockets; use Gnat.Sockets; with Ada.Text_Io; use Ada.Text_Io; with Ada.Exceptions; use Ada.Exceptions; with Ada.Streams; use Ada.Streams; with Ada.Command_Line; use Ada.Command_Line; procedure GetPop3 is -- Constantes globales BUFSIZ : constant := 256; PORT_DEFAUT : constant Port_Type := 110; Protocol_Error : exception; -- Wrapper pour Send_Socket procedure Send(Sock : in Socket_Type; S : in String) is subtype SEA is Stream_Element_Array(1..S'Length); My_SEA : SEA; for My_SEA'Address use S(S'First)'Address; Trash : Stream_Element_Offset; begin Send_Socket(Sock, My_Sea, Trash); end Send; -- Wrapper pour Receive_Socket procedure Receive(Sock : in Socket_Type; S : out String; Taille : out Natural) is subtype SEA is Stream_Element_Array(1..S'Length); My_SEA : SEA; for My_SEA'Address use S(S'First)'Address; Trash : Stream_Element_Offset; begin Receive_Socket(Sock, My_Sea, Trash); Taille := Natural(Trash); end Receive; function Get_Reponse (Sock : Socket_Type) return String is Tampon : String(1..BUFSIZ); Dernier : Natural; begin Receive(Sock, Tampon, Dernier); return Tampon(1..Dernier); end Get_Reponse ; procedure Is_Ok (Reponse : in String) is begin if Reponse(1..3) /= "+OK" then raise Protocol_Error; end if; end Is_Ok; procedure Connexion (Sock : out Socket_Type; Serveur, User, Pass : in String; Port : in Port_Type := PORT_DEFAUT) is Adresse : Sock_Addr_Type; begin -- Construction de l'adresse Adresse.Addr := Addresses(Get_Host_By_Name (Serveur)); Adresse.Port := PORT_DEFAUT; -- Creation et connexion de la socket � l'adresse Initialize; Create_Socket(Sock); Connect_Socket(Sock, Adresse); Is_Ok(Get_Reponse(Sock)); Send(Sock, "user " & User & ASCII.CR & ASCII.LF); Is_Ok(Get_Reponse(Sock)); Send(Sock, "pass " & Pass & ASCII.CR & ASCII.LF); Is_Ok(Get_Reponse(Sock)); end Connexion; procedure Commande (Sock : in Socket_Type; Cde : in String) is begin Send(Sock, Cde & ASCII.CR & ASCII.LF); end Commande; Sock : Socket_Type; begin -- Prog principal if Argument_Count /= 3 then Put_Line("Usage: " & Command_Name & " <serveur> <user> <password>"); else begin Connexion(Sock, Argument(1), Argument(2), Argument(3)); Put_Line("Connexion ok"); Commande(Sock, "stat"); Put_Line(Get_Reponse(Sock)); Close_Socket(Sock); exception when Protocol_Error => Put_Line(Current_Error, "Requete incorrecte"); when E: others => Put_Line(Exception_Name(E) & ": " & Exception_Message(E)); end; end if; end GetPop3; Hope this helps, -- jaco ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 2:42 TCP/IP Sockets with GNAT.Sockets fabio de francesco 2005-05-02 5:58 ` Eric Jacoboni @ 2005-05-02 12:11 ` Adrien Plisson 2005-05-02 14:55 ` fabio de francesco 1 sibling, 1 reply; 23+ messages in thread From: Adrien Plisson @ 2005-05-02 12:11 UTC (permalink / raw) fabio de francesco wrote: > Hello, hello ! > Today is the first time I try to use sockets in Ada programs, even if I > have some practical knowledge of programming with TCP/IP sockets in C. > Because I didn't find any better tutorial on working with GNAT.Sockets > I am relying on comments in file g-socket.ads from GCC/GNAT sources > where there is not a complete and detailed coverage of the subject. > > (1) Do you know any better tutorial? personnally, no. the GNAT reference manual says: "The chapter here simply gives a brief summary of the facilities available. The full documentation is found in the spec file for the package. The full sources of these library packages, including both spec and body, are provided with all GNAT releases." so, you can rely on the comments in g-socket.ads (which contains some full examples). also, the behavior is identical to other sockets implementation (C, Python, or others) so don't hesitate to read manuals for other languages. the only big difference is in Streams, which is Ada specific... [...] > I hadn't too many problems with exchanging messages and everything > works. The problem is that I was only able to use Streams for > communicating between them and I can't understand at all how to use > Receive_Socket() and Send_Socket() because they use > "Stream_Element_Array" and "Stream_Element _Offset" in place of > Strings. I know that by using Streams they can't communicate with C > programs and I've read that Streams are everything but efficient. streams are not specially inefficient (to the contrary, my dear). the problem is that many people do not clearly understand them ! so let's explain Ada streams: streams are defined as a tagged record in Ada.Streams, which is to be derived in order to implement stream specific behavior: how to send or receive data from stream. Streams define 2 procedures for reading and writing data onto them. on this side of streams, data are represented as Stream_Element grouped in Stream_Element_Array. a single Stream_Element may represent a byte you send over the network for example. at this end of streams, there is no data type: what is important is the type of streams you manipulate. on the other end, you are concerned with data types you read from or write to stream, but not with the type of streams. on this end, every streams are equal, may it be file, socket, or anything else. this is achieved through stream oriented attributes: 'Read, 'Write, 'Input and 'Output. those attributes allow you to read or write a specific data type from/to a stream. for example: Integer'Input( S ) will read an integer from the stream S (whatever stream type S is). the behavior of those attribute may be overriden through an attribute definition clause. at this end of streams, there is no stream type: what is important is the type of data you manipulate. in fact, stream attributes are kind of double-dispatching operations... at the light of this explaination, you should re-read ARM95 13.13, and may better understand them. so, now you understand this, you may ask yourself if you really need to use Receive_Socket() or Send_Socket(): they are intended to programmers writing their own stream attributes... (note that this could be useful to communicate with a C program through socket streams). i hope this explaination clarified things a bit and was useful to you (or others)... language lawyers will surely push it a little bit further. -- rien ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 12:11 ` Adrien Plisson @ 2005-05-02 14:55 ` fabio de francesco 2005-05-02 16:10 ` Adrien Plisson 2005-05-02 19:39 ` Björn 0 siblings, 2 replies; 23+ messages in thread From: fabio de francesco @ 2005-05-02 14:55 UTC (permalink / raw) Adrien Plisson wrote: > fabio de francesco wrote: > > Hello, > > hello ! > > > Today is the first time I try to use sockets in Ada programs, even if I > > have some practical knowledge of programming with TCP/IP sockets in C. > > Because I didn't find any better tutorial on working with GNAT.Sockets > > I am relying on comments in file g-socket.ads from GCC/GNAT sources > > where there is not a complete and detailed coverage of the subject. > > > > (1) Do you know any better tutorial? > > personnally, no. the GNAT reference manual says: > "The chapter here simply gives a brief summary of the facilities > available. The full documentation is found in the spec file for the > package. The full sources of these library packages, including both > spec and body, are provided with all GNAT releases." > so, you can rely on the comments in g-socket.ads (which contains some > full examples). >From my message: "...I am relying on comments in file g-socket.ads from GCC/GNAT sources...". Sorry for my poor English, I know that sometimes I'm unable to express clearly, but I had already done exactly what you now suggest. > also, the behavior is identical to other sockets > implementation (C, Python, or others) so don't hesitate to read > manuals for other languages. I also said I already know how to program with sockets in C. > the only big difference is in Streams, which is Ada specific... This is the only problem I wrote I had. I didn't know how to use Send_Socket() and Receive_Socket() because the specs say they take "Stream_Element_Array" and "Stream_Element_Offset" as parameters. If you read g-socket.ads you won't find any usage example either of the above mentioned functions or related parameters. > [...] > > I hadn't too many problems with exchanging messages and everything > > works. The problem is that I was only able to use Streams for > > communicating between them and I can't understand at all how to use > > Receive_Socket() and Send_Socket() because they use > > "Stream_Element_Array" and "Stream_Element _Offset" in place of > > Strings. I know that by using Streams they can't communicate with C > > programs and I've read that Streams are everything but efficient. > > streams are not specially inefficient (to the contrary, my dear). the > problem is that many people do not clearly understand them ! That was what I have found by searching and reading this NG through Google for help in using them right before posting. > so let's explain Ada streams: > > streams are defined as a tagged record in Ada.Streams, which is to be > derived in order to implement stream specific behavior: how to send or > receive data from stream. Streams define 2 procedures for reading and > writing data onto them. on this side of streams, data are represented > as Stream_Element grouped in Stream_Element_Array. a single > Stream_Element may represent a byte you send over the network for > example. > > at this end of streams, there is no data type: what is important is > the type of streams you manipulate. > > on the other end, you are concerned with data types you read from or > write to stream, but not with the type of streams. on this end, every > streams are equal, may it be file, socket, or anything else. this is > achieved through stream oriented attributes: 'Read, 'Write, 'Input and > 'Output. those attributes allow you to read or write a specific data > type from/to a stream. for example: Integer'Input( S ) will read an > integer from the stream S (whatever stream type S is). the behavior of > those attribute may be overriden through an attribute definition clause. > > at this end of streams, there is no stream type: what is important is > the type of data you manipulate. > > in fact, stream attributes are kind of double-dispatching > operations... at the light of this explaination, you should re-read > ARM95 13.13, and may better understand them. Thank you for this detailed explanation. > so, now you understand this, you may ask yourself if you really need > to use Receive_Socket() or Send_Socket(): they are intended to > programmers writing their own stream attributes... (note that this > could be useful to communicate with a C program through socket streams). This is exactly the problem that I have overcome with the help I've had from Eric Jacoboni. Both my client and server programs didn't work at exchanging messages with C programs. After searching the web I discovered I had to use Receive_Socket() and Send_Socket() in order to get over that problem. S : String := "Hello"; SEA : Stream_Element_Array(1..S'Length); for SEA'Address use S(S'First)'Address; Last : Stream_Element_Offset; Send_Socket( Socket, SEA, Last ); This is not exactly what someone can find in a Python or C manual. :-) You're right about the fact that the fault is mine for not knowing Streams while a Socket package isn't required to give any explanations on the usage of a subject that is not so closely related. Anyway the package authors cover about 350 lines with an procedure example only using Streams, without ever saying why and when you should sometimes choose Receive_Socket() and Send_Socket() in place of Streams. > i hope this explaination clarified things a bit and was useful to you > (or others)... language lawyers will surely push it a little bit further. > > -- > rien Thanks, it helped a lot to make me to understand Streams. I hope this time I have been able to make myself clear. fabio de francesco ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 14:55 ` fabio de francesco @ 2005-05-02 16:10 ` Adrien Plisson 2005-05-02 17:56 ` Eric Jacoboni 2005-05-02 19:39 ` Björn 1 sibling, 1 reply; 23+ messages in thread From: Adrien Plisson @ 2005-05-02 16:10 UTC (permalink / raw) fabio de francesco wrote: >>From my message: "...I am relying on comments in file g-socket.ads from > GCC/GNAT sources...". Sorry for my poor English, I know that sometimes > I'm unable to express clearly, but I had already done exactly what you > now suggest. [...] > I also said I already know how to program with sockets in C. i'm sorry if you misunderstood my words: i just wanted to make clear that you did exactly what you had to do, and that there was no other way to go. >>the only big difference is in Streams, which is Ada specific... (this was just an introduction for the next big paragraph...)(french style) [...] > Thank you for this detailed explanation. you're welcome ! > This is exactly the problem that I have overcome with the help I've had > from Eric Jacoboni. Both my client and server programs didn't work at > exchanging messages with C programs. After searching the web I > discovered I had to use Receive_Socket() and Send_Socket() in order to > get over that problem. that's plain wrong... the problem is the use of attributes 'Output on arrays which output array bounds before array data. and since String is an array, String'Output outputs String bounds before string data. (in Ada you are no more in C: a string is not delimited by a null character but has a lower and an upper bound). those bounds are always getting in the way when: 1. you are not aware of their existence on the stream 2. the reader of the stream is not an ada program. anyway, you can get rid of those bounds by using 'Read and 'Write instead of 'Input and 'Output. BUT you have to know that using 'Read on unconstrained arrays (especially on String) is... well... A Bad Thing(tm). (i'm not even sure it works). you should note that the problem is the same in C: when reading a string (sorry an array of char) from a socket, you don't know its length. how can you say you read the whole string, and not a sub-part, or worst, the whole string plus the beginning of the following data ? if you can overcome this problem in C, rest assured you can overcome it in Ada... (the exact default behavior for stream attributes is detailed in ARM95 13.13.2: this includes the behavior for array bounds, type discriminants, tags...) > S : String := "Hello"; > SEA : Stream_Element_Array(1..S'Length); > for SEA'Address use S(S'First)'Address; > Last : Stream_Element_Offset; > Send_Socket( Socket, SEA, Last ); (i'm sorry i'm gonna be a bit rude) beuark ! this is implementation dependant: - what if Character'Size /= Stream_Element'Size ? - what if the memory organization of Stream_Element_Array does not match the one for a String ? (i'm not sure overlays are not a recommended practice, but i may be wrong) you'd better write this: declare Socket : Socket_Type; Channel : Stream_Access; begin -- open your socket here, then... Channel := Stream( Socket ); String'Write( Channel, "Hello" ); -- close your socket here... end; > This is not exactly what someone can find in a Python or C manual. :-) i won't put it in an Ada manual either !! > You're right about the fact that the fault is mine for not knowing > Streams while a Socket package isn't required to give any explanations > on the usage of a subject that is not so closely related. it is not your fault, it is just that manuals/tutorials don't tell much about streams. and don't worry, it took me a long time to understand streams. i just don't want people to encounter the same problems i had with them, that's why i always try to "demystify" streams. > Anyway the package authors cover about 350 lines with an procedure > example only using Streams, without ever saying why and when you should > sometimes choose Receive_Socket() and Send_Socket() in place of > Streams. maybe because you just don't need them ! or only need them when you plainly understand what's behind them. > Thanks, it helped a lot to make me to understand Streams. I hope this > time I have been able to make myself clear. you already made yourself clear... -- rien ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 16:10 ` Adrien Plisson @ 2005-05-02 17:56 ` Eric Jacoboni 2005-05-02 18:30 ` Poul-Erik Andreasen 2005-05-02 20:44 ` Adrien Plisson 0 siblings, 2 replies; 23+ messages in thread From: Eric Jacoboni @ 2005-05-02 17:56 UTC (permalink / raw) In article <42765108$0$22419$ba620e4c@news.skynet.be>, Adrien Plisson <aplisson-news@stochastique.net> wrote: > > S : String := "Hello"; > > SEA : Stream_Element_Array(1..S'Length); > > for SEA'Address use S(S'First)'Address; > > Last : Stream_Element_Offset; > > Send_Socket( Socket, SEA, Last ); > > (i'm sorry i'm gonna be a bit rude) beuark ! Agree. It's not the sort of things i expected to write with Ada... But, that's the only code that fits my needs. > this is implementation dependant: > - what if Character'Size /= Stream_Element'Size ? > - what if the memory organization of Stream_Element_Array does not > match the one for a String ? For the second point, Stream_Element_Array is defined as an array of Stream_Element, so i suppose it match the memory organization of a String, isn't it ? > you'd better write this: > > declare > Socket : Socket_Type; > Channel : Stream_Access; > begin > -- open your socket here, then... > Channel := Stream( Socket ); > > String'Write( Channel, "Hello" ); > -- close your socket here... > end; Have you tried this code with a server not Ada aware? Have you tried to exchange messages with, say, a POP3 server? (to send and to read) I've tried to use Streams for that, but i never succeeded to make it work... If a cleaner solution exists, why the hell cannot we find _any_ example? -- jaco ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 17:56 ` Eric Jacoboni @ 2005-05-02 18:30 ` Poul-Erik Andreasen 2005-05-02 19:10 ` Simon Wright 2005-05-02 20:37 ` TCP/IP Sockets with GNAT.Sockets fabio de francesco 2005-05-02 20:44 ` Adrien Plisson 1 sibling, 2 replies; 23+ messages in thread From: Poul-Erik Andreasen @ 2005-05-02 18:30 UTC (permalink / raw) Eric Jacoboni wrote: > In article <42765108$0$22419$ba620e4c@news.skynet.be>, Adrien Plisson > <aplisson-news@stochastique.net> wrote: > > > >>>S : String := "Hello"; >>>SEA : Stream_Element_Array(1..S'Length); >>>for SEA'Address use S(S'First)'Address; >>>Last : Stream_Element_Offset; >>>Send_Socket( Socket, SEA, Last ); >> >>(i'm sorry i'm gonna be a bit rude) beuark ! > > > Agree. It's not the sort of things i expected to write with Ada... But, > that's the only code that fits my needs. > > >>this is implementation dependant: >>- what if Character'Size /= Stream_Element'Size ? >>- what if the memory organization of Stream_Element_Array does not >>match the one for a String ? > > > For the second point, Stream_Element_Array is defined as an array of > Stream_Element, so i suppose it match the memory organization of a > String, isn't it ? > > >>you'd better write this: >> >>declare >> Socket : Socket_Type; >> Channel : Stream_Access; >>begin >> -- open your socket here, then... >> Channel := Stream( Socket ); >> >> String'Write( Channel, "Hello" ); >> -- close your socket here... >>end; > > > Have you tried this code with a server not Ada aware? Have you tried to > exchange messages with, say, a POP3 server? (to send and to read) I've > tried to use Streams for that, but i never succeeded to make it work... > If a cleaner solution exists, why the hell cannot we find _any_ > example? > I have, actually i am using it rigth now and i works. however If the other end of the socket is a C-style server it will probely demand somthing like the following: String'Write( Channel, "Hello" & character'first); when i read i read characters and stop when i reach character'first. Here is a fixed string sulution declare Channel := Stream( Socket ); Word : string(1.. max_word); counter : natural := 1 begin loop word(counter) := Character'Input (Channel); exit when word(counter) = Character'First; counter := counter + 1; end loop; -- her do what you have to do with Word(1..(counter -1)) end; BTW my C-couterpart program dosn't seems to have anything against String'Output( Channel, "Hello" & character'first) ? ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 18:30 ` Poul-Erik Andreasen @ 2005-05-02 19:10 ` Simon Wright 2005-05-03 13:00 ` Poul-Erik Andreasen 2005-05-02 20:37 ` TCP/IP Sockets with GNAT.Sockets fabio de francesco 1 sibling, 1 reply; 23+ messages in thread From: Simon Wright @ 2005-05-02 19:10 UTC (permalink / raw) Poul-Erik Andreasen <poulerik@pea.dk> writes: > BTW my C-couterpart program dosn't seems to have anything against > String'Output( Channel, "Hello" & character'first) ? Well, that _ought_ to send (a) 4 bytes == 1, which is the lower index of the string (b) 4 bytes == 6, which is the upper index of the string (c) the null-terminated string. So it depends what your C-counterpart did with those strange characers. Why do you say Character'First & not ASCII.NUL? If you don't want to include the bounds, use 'Write. There's nothing wrong with streams, but you do have to know exactly what the language requires the compiler to do! ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 19:10 ` Simon Wright @ 2005-05-03 13:00 ` Poul-Erik Andreasen 2005-05-03 21:48 ` Simon Wright 2005-05-04 8:01 ` Character'First, ASCII.NUL and others (Was: Re: TCP/IP Sockets with GNAT.Sockets) Adrien Plisson 0 siblings, 2 replies; 23+ messages in thread From: Poul-Erik Andreasen @ 2005-05-03 13:00 UTC (permalink / raw) Simon Wright wrote: > Poul-Erik Andreasen <poulerik@pea.dk> writes: > > >>BTW my C-couterpart program dosn't seems to have anything against >>String'Output( Channel, "Hello" & character'first) ? > > > Well, that _ought_ to send > > (a) 4 bytes == 1, which is the lower index of the string > (b) 4 bytes == 6, which is the upper index of the string > (c) the null-terminated string. > So it depends what your C-counterpart did with those strange > characers. It probely just trow them away, i think the reson why is not a problem is that besides being zero terminated the the messages that i sent are requered to start with '$', Anyway i will, ofcourse change to string'write > > Why do you say Character'First & not ASCII.NUL? Not for any partikulari reason. When i started developing job i tried with ASCII.NUL things didn't work out(surely for som other reason); they did when i first was using character'first. (also surely for som other reason); Are there any reason why ASCII.NUL should be better; ASCII.NUL are defined as Character'First; > If you don't want to include the bounds, use 'Write. I will > There's nothing wrong with streams, but you do have to know exactly > what the language requires the compiler to do! Therefor this is realy a nice thread :-) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-03 13:00 ` Poul-Erik Andreasen @ 2005-05-03 21:48 ` Simon Wright 2005-05-04 8:01 ` Character'First, ASCII.NUL and others (Was: Re: TCP/IP Sockets with GNAT.Sockets) Adrien Plisson 1 sibling, 0 replies; 23+ messages in thread From: Simon Wright @ 2005-05-03 21:48 UTC (permalink / raw) Poul-Erik Andreasen <poulerik@pea.dk> writes: > Simon Wright wrote: >> Why do you say Character'First & not ASCII.NUL? > > Not for any partikulari reason. > > When i started developing job i tried with ASCII.NUL > things didn't work out(surely for som other reason); > they did when i first was using character'first. > (also surely for som other reason); > > Are there any reason why ASCII.NUL should be better; > > ASCII.NUL are defined as Character'First; It just seems that ASCII.NUL is a more appropriate name for what you are trying to send .. I suppose Character'Val (0) would also do. It seems almost accidental that Character'First gives the value you need .. the others are more explicitly related to the problem. Just my 2p! ^ permalink raw reply [flat|nested] 23+ messages in thread
* Character'First, ASCII.NUL and others (Was: Re: TCP/IP Sockets with GNAT.Sockets) 2005-05-03 13:00 ` Poul-Erik Andreasen 2005-05-03 21:48 ` Simon Wright @ 2005-05-04 8:01 ` Adrien Plisson 2005-05-04 13:40 ` Poul-Erik Andreasen 1 sibling, 1 reply; 23+ messages in thread From: Adrien Plisson @ 2005-05-04 8:01 UTC (permalink / raw) Poul-Erik Andreasen wrote: > When i started developing job i tried with ASCII.NUL > things didn't work out(surely for som other reason); > they did when i first was using character'first. > (also surely for som other reason); > > Are there any reason why ASCII.NUL should be better; Character'First do not describe the NUL character. i mean, it is the NUL character, but you have to know the implementation details of type Character to see that it's first element is the NUL character. ASCII.NUL states explicitly that you are using the NUL character, that's why its use should be better. anyway, the package ASCII is described in ARM95 J.5, that means it is part of "Obsolescent Features". as said in the ARM, "Use of these features is not recommended in newly written programs.". so it is better than Character'First, but there exists a better way to write this. the better way is the use of Ada.Characters.Latin_1, which defines a constant NUL describing the NUL character. unfortunately, the package name is long, so you may have to write a use clause or a rename. with Ada.Text_IO, Ada.Characters.Latin_1; procedure Test is -- see comments below use Ada.Characters.Latin_1; package ASCII renames Ada.Characters.Latin_1; package Characters renames Ada.Characters.Latin_1; begin Ada.Text_IO.Put( Ada.Characters.Latin_1.NUL ); -- a bit long Ada.Text_IO.Put( NUL ); -- a bit short, NUL what ? -- NUL Character ? not sure... Ada.Text_IO.Put( ASCII.NUL ); -- not recommended, there is -- a risk of confusion Ada.Text_IO.Put( Characters.NUL ); -- this seems better ! end Test; besides all this, when looking at Ada.Characters.Latin_1, we see that NUL is defined this way : NUL : constant Character := Character'Val(0); so if you just need NUL and want to avoid declarations, you may use Character'Val(0), which describes the NUL character better than Character'First. -- rien ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Character'First, ASCII.NUL and others (Was: Re: TCP/IP Sockets with GNAT.Sockets) 2005-05-04 8:01 ` Character'First, ASCII.NUL and others (Was: Re: TCP/IP Sockets with GNAT.Sockets) Adrien Plisson @ 2005-05-04 13:40 ` Poul-Erik Andreasen 0 siblings, 0 replies; 23+ messages in thread From: Poul-Erik Andreasen @ 2005-05-04 13:40 UTC (permalink / raw) Adrien Plisson wrote: > Poul-Erik Andreasen wrote: > >> When i started developing job i tried with ASCII.NUL >> things didn't work out(surely for som other reason); >> they did when i first was using character'first. >> (also surely for som other reason); > > > > >> Are there any reason why ASCII.NUL should be better; > > > Character'First do not describe the NUL character. i mean, it is the NUL > character, but you have to know the implementation details of type > Character to see that it's first element is the NUL character. > > ASCII.NUL states explicitly that you are using the NUL character, that's > why its use should be better. > > anyway, the package ASCII is described in ARM95 J.5, that means it is > part of "Obsolescent Features". as said in the ARM, "Use of these > features is not recommended in newly written programs.". so it is better > than Character'First, but there exists a better way to write this. > > the better way is the use of Ada.Characters.Latin_1, which defines a > constant NUL describing the NUL character. unfortunately, the package > name is long, so you may have to write a use clause or a rename. > > with Ada.Text_IO, > Ada.Characters.Latin_1; > procedure Test is > -- see comments below > use Ada.Characters.Latin_1; > package ASCII renames Ada.Characters.Latin_1; > package Characters renames Ada.Characters.Latin_1; > > begin > Ada.Text_IO.Put( Ada.Characters.Latin_1.NUL ); -- a bit long > > Ada.Text_IO.Put( NUL ); -- a bit short, NUL what ? > -- NUL Character ? not sure... > > Ada.Text_IO.Put( ASCII.NUL ); -- not recommended, there is > -- a risk of confusion > > Ada.Text_IO.Put( Characters.NUL ); -- this seems better ! > end Test; > > besides all this, when looking at Ada.Characters.Latin_1, we see that > NUL is defined this way : > > NUL : constant Character := Character'Val(0); > > so if you just need NUL and want to avoid declarations, you may use > Character'Val(0), which describes the NUL character better than > Character'First. > point taken thanks Poul-Erik Andreasen ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 18:30 ` Poul-Erik Andreasen 2005-05-02 19:10 ` Simon Wright @ 2005-05-02 20:37 ` fabio de francesco 2005-05-02 20:52 ` Adrien Plisson 2005-05-03 13:17 ` Poul-Erik Andreasen 1 sibling, 2 replies; 23+ messages in thread From: fabio de francesco @ 2005-05-02 20:37 UTC (permalink / raw) Poul-Erik Andreasen wrote: > > [...] > > I have, actually i am using it rigth now and i works. however If the > other end of the socket is a C-style server it will probely demand > somthing like the following: How can you know a priori if a remote service is coded in C or Ada or everything else? > > String'Write( Channel, "Hello" & character'first); > > when i read i read characters and stop when i reach character'first. > > Here is a fixed string sulution > > declare > Channel := Stream( Socket ); > Word : string(1.. max_word); > counter : natural := 1 > begin > loop > word(counter) := Character'Input (Channel); > exit when word(counter) = Character'First; > counter := counter + 1; > end loop; > -- her do what you have to do with Word(1..(counter -1)) > end; Is your code reading character by character? If it is I don't think you can use it for designing efficient programs. > BTW my C-couterpart program dosn't seems to have anything against > String'Output( Channel, "Hello" & character'first) ? What I understand from this thread is that T'Output and T'Input add some metadata to the stream. If it is true, communicating programs in other languages must know how to read/write the streams in order to differentiate data from metadata. May be your C-counterpart program contains an algorithm that knows how to do it. Ciao, fabio de francesco ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 20:37 ` TCP/IP Sockets with GNAT.Sockets fabio de francesco @ 2005-05-02 20:52 ` Adrien Plisson 2005-05-03 12:04 ` fabio de francesco 2005-05-03 13:17 ` Poul-Erik Andreasen 1 sibling, 1 reply; 23+ messages in thread From: Adrien Plisson @ 2005-05-02 20:52 UTC (permalink / raw) fabio de francesco wrote: > How can you know a priori if a remote service is coded in C or Ada or > everything else? you don't and you should NEVER assume such a thing. but you should know what protocol is to be used between the client and the server. if the protocol is well-defined (that is: in a language independant way) there is no problem in making any software in any language communicate... > Is your code reading character by character? If it is I don't think you > can use it for designing efficient programs. why not ? another question for you: do you use TCP connections to send small packets ? those TCP frames that can achieve more than 50% overhead are really not efficient... > May be your C-counterpart program > contains an algorithm that knows how to do it. or simply ignore those characters which are non-printable, which is the case with small strings... -- rien ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 20:52 ` Adrien Plisson @ 2005-05-03 12:04 ` fabio de francesco 2005-05-03 12:22 ` Adrien Plisson 0 siblings, 1 reply; 23+ messages in thread From: fabio de francesco @ 2005-05-03 12:04 UTC (permalink / raw) Adrien Plisson wrote: > fabio de francesco wrote: > > How can you know a priori if a remote service is coded in C or Ada or > > everything else? > you don't and you should NEVER assume such a thing. but you should know > what protocol is to be used between the client and the server. if the > protocol is well-defined (that is: in a language independant way) there > is no problem in making any software in any language communicate... Ciao, I know that. I've been programming networking software in C for years. I only objected to that statement: "... however If the other end of the socket is a C-style server it will probely demand somthing like the following:..." > > Is your code reading character by character? If it is I don't think you > > can use it for designing efficient programs. > why not ? I supposed that Ada and C aren't different in that. I mean that, when a C program is to read/write a lot of data from/to a disk file or any other device, it is preferred to read/write large chunks of bytes altogether: FILE *in, *out; size_t nread; char buffer[BUFSIZ]; in = fopen ("file.in", "r"); out = fopen ("file.out", "w"); while ((nread = fread(buffer,sizeof(char),sizeof(buffer),in)) > 0) fwrite(buffer,sizeof(char),nread,out); fclose (in); fclose (out); The first code is faster (20% on my machine) than the following: char b; while ((nread = fread(&b,sizeof(char),1,in)) > 0) fwrite(&b,sizeof(char),1,out); > another question for you: do you use TCP connections to send small > packets ? those TCP frames that can achieve more than 50% overhead are > really not efficient... What does make you think that? If you refer to my posted code, it was only a test to get acquainted to GNAT.Sockets. > > May be your C-counterpart program > > contains an algorithm that knows how to do it. > > or simply ignore those characters which are non-printable, which is the > case with small strings... > > -- > rien Regards, fabio de francesco ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-03 12:04 ` fabio de francesco @ 2005-05-03 12:22 ` Adrien Plisson 0 siblings, 0 replies; 23+ messages in thread From: Adrien Plisson @ 2005-05-03 12:22 UTC (permalink / raw) fabio de francesco wrote: > I only objected to that statement: "... however If the other end of the > socket is a C-style server it will probely demand somthing like the > following:..." sorry, i misunderstood your statement... > I supposed that Ada and C aren't different in that. I mean that, when a > C program is to read/write a lot of data from/to a disk file or any > other device, it is preferred to read/write large chunks of bytes > altogether: you are right, it is faster. but there are some cases where you can't read chunks, especially when you don't know the size of the data you have to read and you can't read too much data. > What does make you think that? If you refer to my posted code, it was > only a test to get acquainted to GNAT.Sockets. i hope so ! but i've already seen people doing this... -- rien ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 20:37 ` TCP/IP Sockets with GNAT.Sockets fabio de francesco 2005-05-02 20:52 ` Adrien Plisson @ 2005-05-03 13:17 ` Poul-Erik Andreasen 1 sibling, 0 replies; 23+ messages in thread From: Poul-Erik Andreasen @ 2005-05-03 13:17 UTC (permalink / raw) fabio de francesco wrote: > Poul-Erik Andreasen wrote: > >>[...] >> >>I have, actually i am using it rigth now and i works. however If the >>other end of the socket is a C-style server it will probely demand >>somthing like the following: > > > How can you know a priori if a remote service is coded in C or Ada or > everything else? You can't, but i make no differens as long as you have the API. If the API requires zeroterminated strings it what you could call a c-style API. It can be written in any langauge, also in Ada and ' still be a C.style > >>String'Write( Channel, "Hello" & character'first); >> >>when i read i read characters and stop when i reach character'first. >> >>Here is a fixed string sulution >> >>declare >> Channel := Stream( Socket ); >> Word : string(1.. max_word); >> counter : natural := 1 >>begin >> loop >> word(counter) := Character'Input (Channel); >> exit when word(counter) = Character'First; >> counter := counter + 1; >> end loop; >> -- her do what you have to do with Word(1..(counter -1)) >>end; > > > Is your code reading character by character? If it is I don't think you > can use it for designing efficient programs. At some level the program vill have to deal with bytes individualy anyway, you could asume that the build in procedure are better optimized, but i dont think that the overhead is significant as long as you use a fixed string as buffer. If you using unbounded_strings, and are adding the incomming character it is a quite different story; > >>BTW my C-couterpart program dosn't seems to have anything against >>String'Output( Channel, "Hello" & character'first) ? > > > What I understand from this thread is that T'Output and T'Input add > some metadata to the stream. If it is true, communicating programs in > other languages must know how to read/write the streams in order to > differentiate data from metadata. May be your C-counterpart program > contains an algorithm that knows how to do it. Yes it requere a special start character. Greeting Poul-Erik Andreasen ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 17:56 ` Eric Jacoboni 2005-05-02 18:30 ` Poul-Erik Andreasen @ 2005-05-02 20:44 ` Adrien Plisson 2005-05-02 22:10 ` Eric Jacoboni 1 sibling, 1 reply; 23+ messages in thread From: Adrien Plisson @ 2005-05-02 20:44 UTC (permalink / raw) Eric Jacoboni wrote: >>(i'm sorry i'm gonna be a bit rude) beuark ! > > Agree. It's not the sort of things i expected to write with Ada... But, > that's the only code that fits my needs. i would rather say: that's the only way you found to fit your need. remember the old Perl adage: there is more than one way to do it ! >>this is implementation dependant: >>- what if Character'Size /= Stream_Element'Size ? >>- what if the memory organization of Stream_Element_Array does not >>match the one for a String ? > > For the second point, Stream_Element_Array is defined as an array of > Stream_Element, so i suppose it match the memory organization of a > String, isn't it ? Stream_Element_Array matches the organization of an array, BUT: - Stream_Element is implementation defined (see ARM95 13.13.1), and this does not guarantee Stream_Element'Size = Character'Size (unless i missed something). strangely, it is 8 bits wide on every platform i used, but i would not bet on it for "exotic" 36 bit platforms for example... - Stream_Element_Array may, for efficiency reason, use a different convention than String, which would render them incompatible. (pragma Convention( C, Stream_Element_Array) for example) - the original code was: for SEA'Address use S(S'First)'Address; which places SEA at the address of the first component of S. this is different from: for SEA'Address use S'Address; however, i'm not fond of overlay, so don't ask me to explain why it is this way... > Have you tried this code with a server not Ada aware? Have you tried to > exchange messages with, say, a POP3 server? (to send and to read) I've > tried to use Streams for that, but i never succeeded to make it work... > If a cleaner solution exists, why the hell cannot we find _any_ > example? this is my Ada client: ========================================================================= with Ada.Text_IO, GNAT.Sockets; procedure Main is use GNAT.Sockets; Address : Sock_Addr_Type := (Family_Inet, Inet_Addr( "127.0.0.1" ), 5555); Socket : Socket_Type; Channel : Stream_Access; Data : String := "hello"; begin Initialize; Create_Socket( Socket ); Connect_Socket( Socket, Address ); Channel := Stream( Socket ); String'Write( Channel, Data ); String'Read( Channel, Data ); Ada.Text_IO.Put_Line( Data ); Close_Socket( Socket ); Finalize; end Main; ========================================================================= this is my Python server: ========================================================================= import socket def main(): server = socket.socket( socket.AF_INET, socket.SOCK_STREAM ) server.bind( ('127.0.0.1', 5555) ) server.listen( 5 ) client, addr = server.accept() data = '' while len( data ) != 5: data += client.recv( 5 ) print data client.send( "world" ) server.close() if __name__ == '__main__': main() ========================================================================= they work together like a charm. ok, ok, ok, i admit it i cheated !! the ada client sends a 5 character long string and waits for a 5 character long string, but the server sends a 5 character long string... if the server sent "grabuuuu !", the client would only get "grabu". as i already pointed to you on fr.comp.lang.ada, what you get from a read is dependant on the PROTOCOL ! all the problem encountered when using streams with sockets are protocol problems: people sends some data on the socket and expect something else at the other end. in my example, i used a simple protocol: the client send 5 characters on the socket then the server sends back 5 other characters. the protocol is the same on both sides. when trying to sends strings over the network, you have to take into account that no 2 languages uses the same representation for strings: C strings are null-terminated, Ada strings are arrays of character with a lower and an upper bound, pascal strings are array of chars with only an upper bound... if you just send c strings and expect ada strings, you only get garbage ! this is the point of knowing ARM95 13.13.2: it allows you to know HOW data are pushed onto streams, thus allowing you to know how to read them back. eventually, you can write your own 'Read and 'Write procedures so that you are sure of what you have on the stream... ultimately, you can combine all the techniques to define powerful language-independant protocols ! -- rien ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 20:44 ` Adrien Plisson @ 2005-05-02 22:10 ` Eric Jacoboni 2005-05-02 23:42 ` tmoran 0 siblings, 1 reply; 23+ messages in thread From: Eric Jacoboni @ 2005-05-02 22:10 UTC (permalink / raw) In article <42769099$0$24172$ba620e4c@news.skynet.be>, Adrien Plisson <aplisson-news@stochastique.net> wrote: > this is my Ada client: Thanks, i'm gonna try to adapt it to my needs... > ========================================================================= > with Ada.Text_IO, > GNAT.Sockets; > procedure Main is > use GNAT.Sockets; > > Address : Sock_Addr_Type := (Family_Inet, Inet_Addr( "127.0.0.1" > ), 5555); > Socket : Socket_Type; > Channel : Stream_Access; > > Data : String := "hello"; > > begin > Initialize; > Create_Socket( Socket ); > Connect_Socket( Socket, Address ); > Channel := Stream( Socket ); > > String'Write( Channel, Data ); > String'Read( Channel, Data ); > Ada.Text_IO.Put_Line( Data ); > > Close_Socket( Socket ); > Finalize; > end Main; > as i already pointed to you on fr.comp.lang.ada, what you get from a > read is dependant on the PROTOCOL ! Well... Given the POP3 RFC: "Responses in the POP3 consist of a status indicator and a keyword possibly followed by additional information. All responses are terminated by a CRLF pair. Responses may be up to 512 characters long, including the terminating CRLF. " So, i understand i have to read in a string and that's how i do with every language i know. The pb with your exemple is that you have wrote both the server and the client : you know the server will always send fixed length strings, but that's not the case in real life. Sometimes the POP3 server will send a "+OK", sometimes a "+OK 20 40", sometimes another string. The protocol itself doesnt convey the length of the answer and that's also true with other well known Internet protocols. How to manage this with a Ada String ? I admit i don't see how to do. > ultimately, you can > combine all the techniques to define powerful language-independant > protocols ! I don't want to define protocols, i just want be able to use an existing protocol and to speak with a server that follow a well known RFC. -- jaco ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 22:10 ` Eric Jacoboni @ 2005-05-02 23:42 ` tmoran 0 siblings, 0 replies; 23+ messages in thread From: tmoran @ 2005-05-02 23:42 UTC (permalink / raw) For POP3 and a bunch of other stuff you need an IO layer that buffers input and lets you read LF terminated strings, similar to Ada.Text_IO.Get_Line. eg type Socket_Type(Max_Line_Length: Positive) is new NC.Sockets.Socket_Type with private; procedure Get_Line(Socket : in out Socket_Type; Line : out String; Last : out Natural; Timeout : in Duration := 30.0); -- Return Line(Line'first .. Last) -- Input up through LF if LF occurs, -- Line(Line'range) if no LF seen, -- or Input up through last received char if timeout or hangup ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 14:55 ` fabio de francesco 2005-05-02 16:10 ` Adrien Plisson @ 2005-05-02 19:39 ` Björn 2005-05-02 20:22 ` fabio de francesco 1 sibling, 1 reply; 23+ messages in thread From: Björn @ 2005-05-02 19:39 UTC (permalink / raw) > If you read g-socket.ads you won't find any usage example either of the > above mentioned functions or related parameters. I agree that the documentation of g-sockets could have been a bit more verbose. Having just completed a program that uses a lot of stuff from g-sockets I learned two things the hard way: * Using g-socket streams to send records does not guarantee that the whole record will be sent in one TCP frame. * UDP/Broadcast does not work well with g-sockets streams. If you are planning to do any serious work with sockets I would recommend to go with Send/Receive instead. Best regards Björn ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 19:39 ` Björn @ 2005-05-02 20:22 ` fabio de francesco 2005-05-09 4:03 ` Dave Thompson 0 siblings, 1 reply; 23+ messages in thread From: fabio de francesco @ 2005-05-02 20:22 UTC (permalink / raw) Björn wrote: > > If you read g-socket.ads you won't find any usage example either of > the > > above mentioned functions or related parameters. > > I agree that the documentation of g-sockets could have been a bit more > verbose. > Having just completed a program that uses a lot of stuff from g-sockets > I learned two things the hard way: > * Using g-socket streams to send records does not guarantee that the > whole record will be sent in one TCP frame. TCP is a byte-stream protocol with NO record boundaries. When reading from a TCP socket in a C program we have always to code the read() in a loop and terminate only when no more characters are read (function returns value 0 of type "ssize_t" that could be an Integer in Ada I suppose). > * UDP/Broadcast does not work well with g-sockets streams. > > If you are planning to do any serious work with sockets I would > recommend to go with Send/Receive instead. Are Send/Receive Ada functions? > Best regards > Björn Ciao, fabio de francesco ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: TCP/IP Sockets with GNAT.Sockets 2005-05-02 20:22 ` fabio de francesco @ 2005-05-09 4:03 ` Dave Thompson 0 siblings, 0 replies; 23+ messages in thread From: Dave Thompson @ 2005-05-09 4:03 UTC (permalink / raw) On 2 May 2005 13:22:41 -0700, "fabio de francesco" <fmdf@tiscali.it> wrote: <snip> > TCP is a byte-stream protocol with NO record boundaries. When reading > from a TCP socket in a C program we have always to code the read() in a > loop and terminate only when no more characters are read (function True -- and important: in the typical program-development environment programs are run in isolation, often slow-stepped, on unloaded machines in a secluded subnet, and most if not all TCP/IP stacks in such environments _do_ "accidentally" preserve buffer boundaries, so that programs depending on this "appear" to work, and only when they are deployed to the real-world net of long, heterogenous, overloaded, and varying paths do they fail, and even then "only" occasionally and unpredictably, except that by Murphy's law some occasions will be when your most important user(s)/customer(s)/prospect(s)/boss(es) are doing something particularly important. Er, -11L I<rant>$ 9L :L I</>$$ (Or, can I combine those as 9:L ? I can't recall.) > returns value 0 of type "ssize_t" that could be an Integer in Ada I > suppose). > Socket-for-TCP read() or recv() returns 0 only when the peer has closed or half-closed, i.e., at "end of file". To read less than all of the data on the connection (but more than 1 octet) you must code to read repeatedly (usually in a loop) until you get all of the expected data, usually determined by a known (fixed or prefix) count or a delimiter; or with no expectation until a nonblocking socket returns -1 and sets (the value accessed by) errno to EAGAIN or EWOULDBLOCK or select/poll indicates no data ready for a sufficient time (which most simply can be any time at all). ssize_t will certainly be some integer type. On most machines addresses are the same "word" size as default integers and thus likely Integer; and even if the usable object size is much smaller than the address size and hence nominal address space it is usually convenient to still use the address size for size_t and ssize_t; but neither of these is required or guaranteed. Whatever binding(s) you use should certainly provide a suitable type definition of this for you. - David.Thompson1 at worldnet.att.net ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2005-05-09 4:03 UTC | newest] Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2005-05-02 2:42 TCP/IP Sockets with GNAT.Sockets fabio de francesco 2005-05-02 5:58 ` Eric Jacoboni 2005-05-02 12:11 ` Adrien Plisson 2005-05-02 14:55 ` fabio de francesco 2005-05-02 16:10 ` Adrien Plisson 2005-05-02 17:56 ` Eric Jacoboni 2005-05-02 18:30 ` Poul-Erik Andreasen 2005-05-02 19:10 ` Simon Wright 2005-05-03 13:00 ` Poul-Erik Andreasen 2005-05-03 21:48 ` Simon Wright 2005-05-04 8:01 ` Character'First, ASCII.NUL and others (Was: Re: TCP/IP Sockets with GNAT.Sockets) Adrien Plisson 2005-05-04 13:40 ` Poul-Erik Andreasen 2005-05-02 20:37 ` TCP/IP Sockets with GNAT.Sockets fabio de francesco 2005-05-02 20:52 ` Adrien Plisson 2005-05-03 12:04 ` fabio de francesco 2005-05-03 12:22 ` Adrien Plisson 2005-05-03 13:17 ` Poul-Erik Andreasen 2005-05-02 20:44 ` Adrien Plisson 2005-05-02 22:10 ` Eric Jacoboni 2005-05-02 23:42 ` tmoran 2005-05-02 19:39 ` Björn 2005-05-02 20:22 ` fabio de francesco 2005-05-09 4:03 ` Dave Thompson
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox