* Using GNAT.Sockets @ 2005-04-13 15:07 markwork66 2005-04-13 15:43 ` Duncan Sands 2005-04-14 14:45 ` Bob Spooner 0 siblings, 2 replies; 24+ messages in thread From: markwork66 @ 2005-04-13 15:07 UTC (permalink / raw) We are just converting to GNAT and I am used to the traditional TCP send/receive using an address and byte count to send/receive data. I've used the Receive_Socket command in GNAT.Sockets and I am having trouble receiving all the bytes. The "Last" parameter is not always equal to the size of the message I'm sending and I don't see a way to call back into the procedure to receive the rest of the bytes. Further, we have many different sized messages and, from my little playing with GNAT sockets, it seemed the "Item" parameter is the only way to specify the number of bytes you want to receive. So, does that mean I would have to declare an array of bytes (the "Item" parameter) for all of my messages and the then do an unchecked conversion or a copy_bytes routine to get the data into my Ada message data type? Any help anybody could provide would be most appreciated. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-13 15:07 Using GNAT.Sockets markwork66 @ 2005-04-13 15:43 ` Duncan Sands 2005-04-15 9:04 ` markp 2005-04-14 14:45 ` Bob Spooner 1 sibling, 1 reply; 24+ messages in thread From: Duncan Sands @ 2005-04-13 15:43 UTC (permalink / raw) To: markwork66; +Cc: comp.lang.ada Hi markwork66, On Wed, 2005-04-13 at 08:07 -0700, markwork66@yahoo.com wrote: > We are just converting to GNAT and I am used to the traditional TCP > send/receive using an address and byte count to send/receive data. I've > used the Receive_Socket command in GNAT.Sockets and I am having trouble > receiving all the bytes. The "Last" parameter is not always equal to > the size of the message I'm sending and I don't see a way to call back > into the procedure to receive the rest of the bytes. there are two things you might be talking about here: (1) Item'Length is less then the size of your message, Last is equal to Item'Last. (2) Last is less than Item'Last, and less than the length of your message (or rather: Last - Item'First + 1 < your message length). In case (1), the operating system has transferred as much into your buffer Item as your buffer can hold. That's the way it should be. To get the rest of the data, call Receive_Socket again. Case (2) happens for Receive_Socket because it happens for the standard C socket routine recv. Receive_Socket is quite low level - it is just a wrapper around recv. recv can return less than the length of your message because either (A) the entire message has not yet arrived on your computer, or your buffer is longer than the socket buffer, (B) the OS feels like it, or (C) an error occurred. You've got to expect (A) - finite speed and finite buffers is a fact of life. As for (B), I'm not being facetious - the OS is allowed to return a "short read" even if it has more data. This is also the case with files by the way: even if you read less than the length of a file, the OS is allowed to nonetheless return less than you asked for. This is rare. As for (C), I guess that's not the problem here. I'm guessing that you would like a higher-level routine that automagically takes care of short reads for you. For that you can use the stream routines. > Further, we have many different sized messages and, from my little > playing with GNAT sockets, it seemed the "Item" parameter is the only > way to specify the number of bytes you want to receive. So, does that > mean I would have to declare an array of bytes (the "Item" parameter) > for all of my messages and the then do an unchecked conversion or a > copy_bytes routine to get the data into my Ada message data type? Probably here too you want the stream stuff. Ciao, Duncan. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-13 15:43 ` Duncan Sands @ 2005-04-15 9:04 ` markp 2005-04-15 9:25 ` Duncan Sands 0 siblings, 1 reply; 24+ messages in thread From: markp @ 2005-04-15 9:04 UTC (permalink / raw) Duncan, Thanks for your reply. In case (1), that is what is occuring. When I call Receive_Socket again to get the rest of the data, I'm wondering if the call will place the new data at the beginning of the item buffer. That would mean I would have to copy it out before I do a subsequent read. Is this the case? I do not want a higher level routine. I would like to stay withing the GNAT.Sockets package. Thanks again. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-15 9:04 ` markp @ 2005-04-15 9:25 ` Duncan Sands 2005-04-18 9:01 ` markp 0 siblings, 1 reply; 24+ messages in thread From: Duncan Sands @ 2005-04-15 9:25 UTC (permalink / raw) To: markp; +Cc: comp.lang.ada Hi markp, > Thanks for your reply. In case (1), that is what is occuring. When I > call Receive_Socket again to get the rest of the data, I'm wondering if > the call will place the new data at the beginning of the item buffer. > That would mean I would have to copy it out before I do a subsequent > read. Is this the case? Suppose your buffer is My_Buffer, and after the first call you see Last < My_Buffer'Last (note that if Last < My_Buffer'First then the connection has gone down). Then you can do the following: procedure Receive_Socket (Socket => My_Socket, Item => My_Buffer (Last + 1 .. My_Buffer'Last), Last => Last); > I do not want a higher level routine. I would like to stay withing the > GNAT.Sockets package. GNAT.Sockets provides higher level routines - the stream stuff. Ciao, Duncan. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-15 9:25 ` Duncan Sands @ 2005-04-18 9:01 ` markp 2005-04-18 13:23 ` Michael Paus 2005-04-18 13:51 ` Marc A. Criley 0 siblings, 2 replies; 24+ messages in thread From: markp @ 2005-04-18 9:01 UTC (permalink / raw) Duncan Sands wrote: > Hi markp, > > > Thanks for your reply. In case (1), that is what is occuring. When I > > call Receive_Socket again to get the rest of the data, I'm wondering if > > the call will place the new data at the beginning of the item buffer. > > That would mean I would have to copy it out before I do a subsequent > > read. Is this the case? > > Suppose your buffer is My_Buffer, and after the first call you see > Last < My_Buffer'Last (note that if Last < My_Buffer'First then the > connection has gone down). Then you can do the following: > > procedure Receive_Socket > (Socket => My_Socket, > Item => My_Buffer (Last + 1 .. My_Buffer'Last), > Last => Last); > > > I do not want a higher level routine. I would like to stay withing the > > GNAT.Sockets package. > > GNAT.Sockets provides higher level routines - the stream stuff. > > Ciao, > > Duncan. Duncan, Thanks for your reply. It does what I want it to do. I have one other question. My assumption is that I have to read the data into My_buffer, which is of a type Stream_Elemet_Array. If there a way to read the data directly into an Ada record type, as opposed to a Stream_Element_Array? Otherwise, I will have to read the socket and then copy the bytes into the record type and act on it there. Is there a way to avoid this extra copy and go directly to my data type? Thanks once again for your help, Mark ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 9:01 ` markp @ 2005-04-18 13:23 ` Michael Paus 2005-04-18 14:32 ` markp 2005-04-18 13:51 ` Marc A. Criley 1 sibling, 1 reply; 24+ messages in thread From: Michael Paus @ 2005-04-18 13:23 UTC (permalink / raw) markp wrote: > Thanks for your reply. It does what I want it to do. I have one other > question. My assumption is that I have to read the data into My_buffer, > which is of a type Stream_Elemet_Array. If there a way to read the data > directly into an Ada record type, as opposed to a Stream_Element_Array? > Otherwise, I will have to read the socket and then copy the bytes into > the record type and act on it there. Is there a way to avoid this extra > copy and go directly to my data type? That's where the "stream stuff" comes into play. If you use a socket stream instead of a plain socket you do not have to care about buffer sizes and such stuff. Instead you can then use the stream attributes of your record type. Something like declare Rec : My_Record := My_Record'Input(My_Socket_Stream_Access); begin ... end; Michael ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 13:23 ` Michael Paus @ 2005-04-18 14:32 ` markp 2005-04-18 15:14 ` Adrien Plisson 0 siblings, 1 reply; 24+ messages in thread From: markp @ 2005-04-18 14:32 UTC (permalink / raw) Micheal, Thanks for your input. I tried what you said but could not get it to work. Here is what I did: type Data_Type is array(1..800) of Byte; Data : Data_Type := (others => 0); . . <Created socket using GNAT.Sockets> . . After successful connection I did the following: My_Stream_Access := GNAT.Sockets.Stream(Socket => Socket); Then, I tried to read the socket as follows: Data := Data_Type'Input(My_Stream_Access); The data I got was incorrect. What di dI do wrong? Thanks again for your help. Mark ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 14:32 ` markp @ 2005-04-18 15:14 ` Adrien Plisson 2005-04-18 15:35 ` markp 0 siblings, 1 reply; 24+ messages in thread From: Adrien Plisson @ 2005-04-18 15:14 UTC (permalink / raw) markp wrote: > type Data_Type is array(1..800) of Byte; > Data : Data_Type := (others => 0); > .. > .. > <Created socket using GNAT.Sockets> > .. > .. > After successful connection I did the following: > > My_Stream_Access := GNAT.Sockets.Stream(Socket => Socket); > > Then, I tried to read the socket as follows: > > Data := Data_Type'Input(My_Stream_Access); > > The data I got was incorrect. What di dI do wrong? who sent the 800 bytes you read on the network ? is it an Ada application using streams too (and specifically Data_Type'Output)? -- rien ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 15:14 ` Adrien Plisson @ 2005-04-18 15:35 ` markp 2005-04-18 15:48 ` Adrien Plisson 0 siblings, 1 reply; 24+ messages in thread From: markp @ 2005-04-18 15:35 UTC (permalink / raw) No, It is an Ada program that does not use streams. It uses simply address/byte count passed to the TCP. I'm guessing by your answer it must use streams also. I don't have control over the other side, so, does this mean I will not be able to use streams on my side? Mark ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 15:35 ` markp @ 2005-04-18 15:48 ` Adrien Plisson 2005-04-18 17:06 ` markp 0 siblings, 1 reply; 24+ messages in thread From: Adrien Plisson @ 2005-04-18 15:48 UTC (permalink / raw) markp wrote: > No, > > It is an Ada program that does not use streams. It uses simply > address/byte count passed to the TCP. I'm guessing by your answer it > must use streams also. I don't have control over the other side, so, > does this mean I will not be able to use streams on my side? > > Mark the 'Input attribute, when used on an array type, first tries to read the bounds of the array (ARM95 13.13.2 §26). those bounds are definitely NOT part of the data received, since the sender did not use streams, and that may explain the corruption you encountered (you are lucky: on fr.comp.lang.ada, another poster got a Storage_Error). the solution is: - either use 'Read and 'Write instead of 'Input and 'Output - or rewrite the sender so that it uses 'Input and 'Output. you should read ARM95 13.13.2 to understand what data are placed on the stream when using stream attributes. -- rien ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 15:48 ` Adrien Plisson @ 2005-04-18 17:06 ` markp 2005-04-18 18:23 ` markp 2005-04-18 20:45 ` Eric Jacoboni 0 siblings, 2 replies; 24+ messages in thread From: markp @ 2005-04-18 17:06 UTC (permalink / raw) I have no control on the other side. I tried using the 'Read, but it wants 2 parameters. Can you tell me what they are? Lastly, when the socket connection is lost, by using streams, what kind of feedback should I expect? An exception? Mark ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 17:06 ` markp @ 2005-04-18 18:23 ` markp 2005-04-18 20:45 ` Eric Jacoboni 1 sibling, 0 replies; 24+ messages in thread From: markp @ 2005-04-18 18:23 UTC (permalink / raw) I figured out the parameters for the read call. Data_Type'Read( My_Stream_Access, Data); However, when I tried to send a different type of message immediately after the first one, I get an exception:ADA.IO_EXCEPTIONS.END_ERROR. What do I need to fix this? Thanks, Mark ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 17:06 ` markp 2005-04-18 18:23 ` markp @ 2005-04-18 20:45 ` Eric Jacoboni 2005-04-18 21:30 ` Pascal Obry 1 sibling, 1 reply; 24+ messages in thread From: Eric Jacoboni @ 2005-04-18 20:45 UTC (permalink / raw) "markp" <markwork66@yahoo.com> writes: > I have no control on the other side. I tried using the 'Read, but it > wants 2 parameters. Can you tell me what they are? I've had the same problem : writing a simple POP3 client with Gnat.Sockets and Streams is not so easy. Looks like streams are good when you write both the server and the clients apps, but not when you have to talk to a existing server (at least, it's the conclusion where i am now). I think i've found a solution to circumvent this problem : using Gnat.Sockets.Send_Socket and Gnat.Sockets.Receive_Socket procedures. The problem, now, is to play (well... to fight) with unchecked conversions between Stream_Element_Array/Stream_Element_Offset and String/Positive in both direction... If only AdaSockets wanted to build ok on my plateform! -- �ric Jacoboni, n� il y a 1417300708 secondes ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 20:45 ` Eric Jacoboni @ 2005-04-18 21:30 ` Pascal Obry 2005-04-18 23:00 ` Eric Jacoboni 0 siblings, 1 reply; 24+ messages in thread From: Pascal Obry @ 2005-04-18 21:30 UTC (permalink / raw) Eric Jacoboni <jaco@neottia.net> writes: > I've had the same problem : writing a simple POP3 client with > Gnat.Sockets and Streams is not so easy. Looks like streams are good FYI, a POP3 client is provided with AWS. I must say that it is quite trivial and works on top of AWS.Net's socket layer (based on GNAT.Sockets or AdaSockets implementations). You can also have a look at the WebMail service which uses the SMTP and POP3 protocols. Pascal. -- --|------------------------------------------------------ --| Pascal Obry Team-Ada Member --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE --|------------------------------------------------------ --| http://www.obry.net --| "The best way to travel is by means of imagination" --| --| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595 ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 21:30 ` Pascal Obry @ 2005-04-18 23:00 ` Eric Jacoboni 2005-04-19 7:04 ` Pascal Obry 2005-04-19 17:36 ` Björn Lundin 0 siblings, 2 replies; 24+ messages in thread From: Eric Jacoboni @ 2005-04-18 23:00 UTC (permalink / raw) Pascal Obry <pascal@obry.net> writes: > FYI, a POP3 client is provided with AWS. Yes, i know. But AWS cannot solve my particular problem as: 1) Like AdaSockets, it refuses to build on my system (Mac OS X) and i've no so much time/skill to investigate more on that. 2) I was talking about POP3 just for the record. In fact, i'm searching some running examples of Ada code to show to my students that is a life beside socket(2) while staying on a relative "low" level. -- �ric Jacoboni, n� il y a 1417308967 secondes ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 23:00 ` Eric Jacoboni @ 2005-04-19 7:04 ` Pascal Obry 2005-04-19 17:36 ` Björn Lundin 1 sibling, 0 replies; 24+ messages in thread From: Pascal Obry @ 2005-04-19 7:04 UTC (permalink / raw) Eric Jacoboni <jaco@neottia.net> writes: > 1) Like AdaSockets, it refuses to build on my system (Mac OS X) and > i've no so much time/skill to investigate more on that. I know some people have been able to build AWS on Mac OSX. But I can't help. Pascal. -- --|------------------------------------------------------ --| Pascal Obry Team-Ada Member --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE --|------------------------------------------------------ --| http://www.obry.net --| "The best way to travel is by means of imagination" --| --| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595 ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 23:00 ` Eric Jacoboni 2005-04-19 7:04 ` Pascal Obry @ 2005-04-19 17:36 ` Björn Lundin 2005-04-19 19:08 ` Eric Jacoboni 1 sibling, 1 reply; 24+ messages in thread From: Björn Lundin @ 2005-04-19 17:36 UTC (permalink / raw) To: Eric Jacoboni; +Cc: comp.lang.ada 2005-04-19 kl. 01.00 skrev Eric Jacoboni: > > 1) Like AdaSockets, it refuses to build on my system (Mac OS X) and > i've no so much time/skill to investigate more on that. if you can live with linking it static, download adasockets 1.8.4.7 then put sockets-constants.ads sockets-naming.ads sockets-utils.adb sockets-link.ads sockets-stream_io.adb sockets-utils.ads sockets-multicast.adb sockets-stream_io.ads sockets.adb sockets-multicast.ads sockets-thin.ads sockets.ads sockets-naming.adb sockets-types.ads test.adb into a directory in your SOURCE_PATH of gnat (socket-thin.ads was called socket-thin.ads.unix, and sockets-constants.ads was generated by modifying the constants.sh script some constnts failed, but I did not bother, but the failed ones are: constants.c:150: error: `FIOSSAIOOWN' undeclared (first use in this function) constants.c:150: error: `I_SETSIG' undeclared (first use in this function) constants.c:150: error: `S_RDNORM' undeclared (first use in this function) constants.c:150: error: `S_WRNORM' undeclared (first use in this function) minimac: bnl$ cat sockets-constants.ads -- This package has been generated automatically on: -- Darwin minimac.lundin.homelinux.net 7.9.0 Darwin Kernel Version -- 7.9.0: Wed Mar 30 20:11:17 PST 2005; root:xnu/xnu-517.12.7.obj~1/RELEASE_P -- PC Power Macintosh powerpc -- Generation date: Tue Apr 19 19:09:06 CEST 2005 -- Any change you make here is likely to be lost ! package Sockets.Constants is Tcp_Nodelay : constant := 16#0001#; Af_Inet : constant := 16#0002#; Af_Unix : constant := 16#0001#; Sock_Stream : constant := 16#0001#; Sock_Dgram : constant := 16#0002#; Eintr : constant := 16#0004#; Eagain : constant := 16#0023#; Ewouldblock : constant := 16#0023#; Einprogress : constant := 16#0024#; Ealready : constant := 16#0025#; Eisconn : constant := 16#0038#; Econnrefused : constant := 16#003D#; Fndelay : constant := 16#0004#; Fioasync : constant := -2147195267; F_Getfl : constant := 16#0003#; F_Setfl : constant := 16#0004#; Fiossaioown : constant := 16#0004#; So_Rcvbuf : constant := 16#1002#; So_Reuseaddr : constant := 16#0004#; So_Reuseport : constant := 16#0200#; Sol_Socket : constant := 16#FFFF#; Sigterm : constant := 16#000F#; Sigkill : constant := 16#0009#; O_Rdonly : constant := 16#0000#; O_Wronly : constant := 16#0001#; O_Rdwr : constant := 16#0002#; Host_Not_Found : constant := 16#0001#; Try_Again : constant := 16#0002#; No_Recovery : constant := 16#0003#; No_Data : constant := 16#0004#; No_Address : constant := 16#0004#; Pollin : constant := 16#0001#; Pollpri : constant := 16#0002#; Pollout : constant := 16#0004#; Pollerr : constant := 16#0008#; Pollhup : constant := 16#0010#; Pollnval : constant := 16#0020#; I_Setsig : constant := 16#0020#; S_Rdnorm : constant := 16#0020#; S_Wrnorm : constant := 16#0020#; Ipproto_Ip : constant := 16#0000#; Ip_Add_Membership : constant := 16#000C#; Ip_Multicast_Loop : constant := 16#000B#; Ip_Multicast_Ttl : constant := 16#000A#; Ip_Drop_Membership : constant := 16#000D#; O_Nonblock : constant := 16#0004#; Msg_Peek : constant := 16#0002#; Fionbio : constant := -2147195266; Fionread : constant := 16#4004667F#; So_Sndbuf : constant := 16#1001#; Af_Inet6 : constant := 16#001E#; Ai_Addrconfig : constant := 16#0400#; Ai_All : constant := 16#0100#; Ai_Canonname : constant := 16#0002#; Ai_Default : constant := 16#0600#; Ai_Mask : constant := 16#0007#; Ai_Numerichost : constant := 16#0004#; Ai_Passive : constant := 16#0001#; Ai_V4mapped : constant := 16#0800#; Ai_V4mapped_Cfg : constant := 16#0200#; Ni_Dgram : constant := 16#0010#; Ni_Maxhost : constant := 16#0401#; Ni_Maxserv : constant := 16#0020#; Ni_Namereqd : constant := 16#0004#; Ni_Nofqdn : constant := 16#0001#; Ni_Numerichost : constant := 16#0002#; Ni_Numericserv : constant := 16#0008#; Ni_Withscopeid : constant := 16#0020#; Ipproto_Ipv6 : constant := 16#0029#; Ipv6_Unicast_Hops : constant := 16#0004#; Ipv6_Multicast_If : constant := 16#0009#; Ipv6_Multicast_Hops : constant := 16#000A#; Ipv6_Multicast_Loop : constant := 16#000B#; Ipv6_Join_Group : constant := 16#000C#; Ipv6_Leave_Group : constant := 16#000D#; end Sockets.Constants; By doing this, I get to use 'socket' 'connect' put_line' and 'get' properly by testing with my webserver minimac: bnl$ cat test.adb with sockets; use sockets; with Text_io; procedure test is My_sock : socket_fd; begin Socket(My_sock); Connect(My_Sock,"della",80); Put_Line(My_Sock, "GET /"); Text_Io.Put_Line(Get(My_Sock)); end test; > Björn Lundin bnl at spray dot se ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-19 17:36 ` Björn Lundin @ 2005-04-19 19:08 ` Eric Jacoboni 0 siblings, 0 replies; 24+ messages in thread From: Eric Jacoboni @ 2005-04-19 19:08 UTC (permalink / raw) Bj�rn Lundin <bnl@spray.se> writes: > if you can live with linking it static [snip] Thanks a lot, it works! -- �ric Jacoboni, n� il y a 1417381620 secondes ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-18 9:01 ` markp 2005-04-18 13:23 ` Michael Paus @ 2005-04-18 13:51 ` Marc A. Criley 1 sibling, 0 replies; 24+ messages in thread From: Marc A. Criley @ 2005-04-18 13:51 UTC (permalink / raw) markp wrote: > Thanks for your reply. It does what I want it to do. I have one other > question. My assumption is that I have to read the data into My_buffer, > which is of a type Stream_Elemet_Array. If there a way to read the data > directly into an Ada record type, as opposed to a Stream_Element_Array? > Otherwise, I will have to read the socket and then copy the bytes into > the record type and act on it there. Is there a way to avoid this extra > copy and go directly to my data type? Take a look at "A Socket-Based Manifestion of Streams" at http://www.sigada.org/ada_letters/june2001/socket_streams.pdf Marc A. Criley ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-13 15:07 Using GNAT.Sockets markwork66 2005-04-13 15:43 ` Duncan Sands @ 2005-04-14 14:45 ` Bob Spooner 2005-04-15 9:06 ` markp 1 sibling, 1 reply; 24+ messages in thread From: Bob Spooner @ 2005-04-14 14:45 UTC (permalink / raw) Hi Markwork66, <markwork66@yahoo.com> wrote in message news:1113404846.310840.322920@z14g2000cwz.googlegroups.com... > We are just converting to GNAT and I am used to the traditional TCP > send/receive using an address and byte count to send/receive data. I've > used the Receive_Socket command in GNAT.Sockets and I am having trouble > receiving all the bytes. The "Last" parameter is not always equal to > the size of the message I'm sending and I don't see a way to call back > into the procedure to receive the rest of the bytes. > > Further, we have many different sized messages and, from my little > playing with GNAT sockets, it seemed the "Item" parameter is the only > way to specify the number of bytes you want to receive. So, does that > mean I would have to declare an array of bytes (the "Item" parameter) > for all of my messages and the then do an unchecked conversion or a > copy_bytes routine to get the data into my Ada message data type? > > Any help anybody could provide would be most appreciated. > I'm assuming that you are using TCP/IP, which is a stream-oriented protocol. The messages you are sending may be broken up into shorter lengths depending on the characteristics of the underlying mechanism used for moving the information. There are several solutions to your problem, among them: 1) If you are using the same compiler and type of computer, operating system, etc. at both ends of the circuit, you can use the default streams mechanism to send the messages by using the Input and Output attributes. Unlike C++, the default representation format for the streams facility for Ada is binary rather than ASCII. 2) You can layer a record protocol on top of TCP/IP where you prepend your message with a fixed-length integer field representing the number of bytes in the message. Then when you receive the message, you first read the number of bytes, and then issue additional reads until you have received the entire message. I hope this helps. Bob ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-14 14:45 ` Bob Spooner @ 2005-04-15 9:06 ` markp 2005-04-15 11:47 ` Michael Paus 0 siblings, 1 reply; 24+ messages in thread From: markp @ 2005-04-15 9:06 UTC (permalink / raw) Bob, Thanks for your reply. My basic quesion is I realize that a socket read will not necessarily return all the data requested. The Receive_Socket item input parameter takes and array. Will a subsequent read place data at the beginning of the array, meaning I have to copy data out before I read again? Thanks again. ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-15 9:06 ` markp @ 2005-04-15 11:47 ` Michael Paus 2005-04-15 14:07 ` Bob Spooner 0 siblings, 1 reply; 24+ messages in thread From: Michael Paus @ 2005-04-15 11:47 UTC (permalink / raw) markp wrote: > Bob, > > Thanks for your reply. My basic quesion is I realize that a socket read > will not necessarily return all the data requested. The Receive_Socket > item input parameter takes and array. Will a subsequent read place data > at the beginning of the array, meaning I have to copy data out before I > read again? Yes it does but you do not have to copy your data. Just have a look at Duncans example. He told you already how to do it. You just have to call this in a loop until Last = My_Buffer'Last. procedure Receive_Socket (Socket => My_Socket, Item => My_Buffer (Last + 1 .. My_Buffer'Last), Last => Last); The first byte will be stored at the first position of the buffer array you provide, but in the above example we specify a sub-range of the whole buffer and so the first element of this is at the index Last + 1 of the whole buffer and this is exactly what you need. Michael ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-15 11:47 ` Michael Paus @ 2005-04-15 14:07 ` Bob Spooner 2005-04-17 15:35 ` Michael Paus 0 siblings, 1 reply; 24+ messages in thread From: Bob Spooner @ 2005-04-15 14:07 UTC (permalink / raw) Well, it's not _quite_ that simple... "Michael Paus" <pausnospam@nospamib-paus.com> wrote in message news:d3o9le$cgm$1@online.de... > markp wrote: > > > Bob, > > > > Thanks for your reply. My basic quesion is I realize that a socket read > > will not necessarily return all the data requested. The Receive_Socket > > item input parameter takes and array. Will a subsequent read place data > > at the beginning of the array, meaning I have to copy data out before I > > read again? > > Yes it does but you do not have to copy your data. Just have a look at > Duncans example. He told you already how to do it. You just have to call > this in a loop until Last = My_Buffer'Last. > > procedure Receive_Socket > (Socket => My_Socket, > Item => My_Buffer (Last + 1 .. My_Buffer'Last), > Last => Last); > > The first byte will be stored at the first position of the buffer array > you provide, but in the above example we specify a sub-range of the > whole buffer and so the first element of this is at the index Last + 1 > of the whole buffer and this is exactly what you need. > > Michael Your buffer needs to be big enough to read the largest message you expect, and for the shorter messages, you need to use a slice of the buffer equal to the size of the message being read so that you don't read in some of the following message along with the current message. Bob ^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: Using GNAT.Sockets 2005-04-15 14:07 ` Bob Spooner @ 2005-04-17 15:35 ` Michael Paus 0 siblings, 0 replies; 24+ messages in thread From: Michael Paus @ 2005-04-17 15:35 UTC (permalink / raw) Bob Spooner wrote: > Well, it's not _quite_ that simple... > "Michael Paus" <pausnospam@nospamib-paus.com> wrote in message > news:d3o9le$cgm$1@online.de... > >>markp wrote: >> >> >>>Bob, >>> >>>Thanks for your reply. My basic quesion is I realize that a socket read >>>will not necessarily return all the data requested. The Receive_Socket >>>item input parameter takes and array. Will a subsequent read place data >>>at the beginning of the array, meaning I have to copy data out before I >>>read again? >> >>Yes it does but you do not have to copy your data. Just have a look at >>Duncans example. He told you already how to do it. You just have to call >>this in a loop until Last = My_Buffer'Last. >> >> procedure Receive_Socket >> (Socket => My_Socket, >> Item => My_Buffer (Last + 1 .. My_Buffer'Last), >> Last => Last); >> >>The first byte will be stored at the first position of the buffer array >>you provide, but in the above example we specify a sub-range of the >>whole buffer and so the first element of this is at the index Last + 1 >>of the whole buffer and this is exactly what you need. >> >>Michael > > > Your buffer needs to be big enough to read the largest message you expect, > and for the shorter messages, you need to use a slice of the buffer equal to > the size of the message being read so that you don't read in some of the > following message along with the current message. Yes, of course the assumption in the above example is that your intention is to finally read exactly My_Buffer'Length bytes. Michael ^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2005-04-19 19:08 UTC | newest] Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2005-04-13 15:07 Using GNAT.Sockets markwork66 2005-04-13 15:43 ` Duncan Sands 2005-04-15 9:04 ` markp 2005-04-15 9:25 ` Duncan Sands 2005-04-18 9:01 ` markp 2005-04-18 13:23 ` Michael Paus 2005-04-18 14:32 ` markp 2005-04-18 15:14 ` Adrien Plisson 2005-04-18 15:35 ` markp 2005-04-18 15:48 ` Adrien Plisson 2005-04-18 17:06 ` markp 2005-04-18 18:23 ` markp 2005-04-18 20:45 ` Eric Jacoboni 2005-04-18 21:30 ` Pascal Obry 2005-04-18 23:00 ` Eric Jacoboni 2005-04-19 7:04 ` Pascal Obry 2005-04-19 17:36 ` Björn Lundin 2005-04-19 19:08 ` Eric Jacoboni 2005-04-18 13:51 ` Marc A. Criley 2005-04-14 14:45 ` Bob Spooner 2005-04-15 9:06 ` markp 2005-04-15 11:47 ` Michael Paus 2005-04-15 14:07 ` Bob Spooner 2005-04-17 15:35 ` Michael Paus
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox