Prev: Doubling the number of Ada libraries in Fedora
Next: Operation can be dispatching in only one type
From: mockturtle on 12 Nov 2009 14:28 Dear all, I have a strange problem (which, actually, is a problem only because I have to use a buggy server) with the following code that sends an HTTP request to the port 3000 of localhost (server and program run on the same PC) ------- with Ada.Text_IO; use Ada.Text_IO; with GNAT.Sockets; use GNAT.Sockets; with Ada.Streams; use Ada.Streams; with Ada.Characters.Latin_1; procedure main is Sock : Socket_Type; Server : Sock_Addr_Type := (Family => Family_Inet, Addr => Inet_Addr("127.0.0.1"), Port => Port_Type(3000)); Basic_Stream : Stream_Access; Query : String := "GET /p2p.rb? stream=pippo&command=join_user&user=127.0.0.1:48946:3 HTTP/1.1"; Crlf : String := Ada.Characters.Latin_1.CR & Ada.Characters.Latin_1.LF; Host_name : String := "Host: 127.0.0.1:3000"; begin Create_Socket (Sock); Connect_Socket (Sock, Server); Basic_Stream := Stream (Sock); String'Write(Basic_Stream, Query); String'Write(Basic_Stream, Crlf); String'Write(Basic_Stream, Host_Name); String'Write(Basic_Stream, Crlf); String'Write(Basic_Stream, Crlf); end main; ------ If I compile the code at home and check the traffic with tcpdump, I can see that each strings is transmited in a packet by itself. If I compile the code above at work, I see that the strings are transmitted one char per packet (i.e., first a packet with "G", then a packet with "E", and so on...) . It seems that the server does not like this and it closes the connection without replying. However, sometime (in a random fashion) after sending few single char packets, it send the remainder of the string in a single packet. In this case the server replies. [Yes, the server is buggy since it should not care... Anyway, that is what I have to use. Before you object, it is just to carry out some fast-and-dirty tests, so it does not matter much if the system is a little "brittle".]. We tried several tests. For example, if we use C (I'll have to whash my keyboard with soap... ;-) or Ruby, each string is sent in a packet by itself, both at home and at work. I am beginning to think that this is something in the GNAT library and how it interfaces with BSD sockets. Ideas? My environments: Work : GPS 4.3.1 and GNAT 4.3.2 (from "About"), Linux 2.6.something Home: GPS 4.3.1 and GNAT GPL 2009 (20090519), Linux 2.4.26 Thank you in advance.
From: Dmitry A. Kazakov on 12 Nov 2009 15:32 On Thu, 12 Nov 2009 11:28:22 -0800 (PST), mockturtle wrote: > I have a strange problem (which, actually, is a problem only because I > have to use a buggy server) with the following code that sends an HTTP > request to the port 3000 of localhost (server and program run on the > same PC) [...] > String'Write(Basic_Stream, Query); > String'Write(Basic_Stream, Crlf); > String'Write(Basic_Stream, Host_Name); > String'Write(Basic_Stream, Crlf); > String'Write(Basic_Stream, Crlf); > end main; > ------ > > If I compile the code at home and check the traffic with tcpdump, I > can see that each strings is transmited in a packet by itself. > > If I compile the code above at work, I see that the strings are > transmitted one char per packet (i.e., first a packet with "G", then a > packet with "E", and so on...) When you write an array into a stream using the attribute 'Write, the compiler has right to implement this as individual writings of the array elements. Newer versions of GNAT coalesce string writing into several characters at once, the older ones do not. So the first thing to do is to use Stream operations rather than the attributes. E.g. Write procedure Write( Stream : in out Root_Stream_Type; Item : in Stream_Element_Array) Even better would be to use Send from GNAT sockets. With Send you can be certain that the packet will be split only if the transport layer urgently will do this. Another thing is a strange behavior of the socket (TCP stack), which normally coalesces small packets. There is a TCP_NO_DELAY option which controls this behavior. By default it is false, i.e. coalescing is on. Make sure that you don't set it to true when you create the socket. You can also set it to false explicitly. > My environments: > Work : GPS 4.3.1 and GNAT 4.3.2 (from "About"), Linux 2.6.something > Home: GPS 4.3.1 and GNAT GPL 2009 (20090519), Linux 2.4.26 See, the compilers are indeed different! -- Regards, Dmitry A. Kazakov http://www.dmitry-kazakov.de
From: Jacob Sparre Andersen on 12 Nov 2009 15:46 mockturtle <framefritti(a)gmail.com> writes: > String'Write(Basic_Stream, Query); > If I compile the code at home and check the traffic with tcpdump, I > can see that each strings is transmited in a packet by itself. > > If I compile the code above at work, I see that the strings are > transmitted one char per packet (i.e., first a packet with "G", then a > packet with "E", and so on...) > Ideas? I think what you see is simply different implementations of the "Write" attribute for arrays. You can work around the difference by supplying your own implementation of the "Write" attribute for strings, which calls "Ada.Streams.Write" with a storage element array overlayed with the complete string to be written. Greetings, Jacob -- �Verbing weirds language.� -- Calvin
|
Pages: 1 Prev: Doubling the number of Ada libraries in Fedora Next: Operation can be dispatching in only one type |