source: ada-examples/pingpong/pingpong.adb @ bf85c63

ada-examples-4-10-branchada-examples-4-9-branch
Last change on this file since bf85c63 was bf85c63, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 17, 2007 at 8:55:02 PM

2007-10-17 Joel Sherrill <joel.sherrill@…>

  • pingpong.adb: Adding new tests as improvements are made to the RTEMS port of the GNAT run-time.
  • Property mode set to 100644
File size: 7.8 KB
Line 
1with Ada.Text_IO;
2with Ada.Exceptions; use Ada.Exceptions;
3with GNAT.Sockets;   use GNAT.Sockets;
4
5procedure PingPong is
6
7   Group : constant String := "239.255.128.128";
8   --  Multicast groupe: administratively scoped IP address
9   --
10   task Pong is
11      entry Start;
12      entry Stop;
13   end Pong;
14
15   task body Pong is
16      Address  : Sock_Addr_Type;
17      Server   : Socket_Type;
18      Socket   : Socket_Type;
19      Channel  : Stream_Access;
20
21   begin
22      accept Start;
23      --
24      --  Get an Internet address of a host (here the local host name).
25      --  Note that a host can have several addresses. Here we get
26      --  the first one which is supposed to be the official one.
27      --
28      Ada.Text_IO.Put_Line ("PONG: Get_Host_By_Name" & Host_Name);
29      Address.Addr := Addresses (Get_Host_By_Name (Host_Name), 1);
30      Ada.Text_IO.Put_Line ("PONG: Back from Get_Host_By_Name");
31
32      --
33      --  Get a socket address that is an Internet address and a port
34      --
35      Address.Port := 5432;
36      --
37      --  The first step is to create a socket. Once created, this
38      --  socket must be associated to with an address. Usually only
39      --  a server (Pong here) needs to bind an address explicitly.
40      --  Most of the time clients can skip this step because the
41      --  socket routines will bind an arbitrary address to an unbound
42      --  socket.
43      --
44      Create_Socket (Server);
45      --
46      --  Allow reuse of local addresses.
47      --
48      Set_Socket_Option
49        (Server,
50         Socket_Level,
51         (Reuse_Address, True));
52
53      Bind_Socket (Server, Address);
54      --
55      --  A server marks a socket as willing to receive connect events.
56      --
57      Listen_Socket (Server);
58      --
59      --  Once a server calls Listen_Socket, incoming connects events
60      --  can be accepted. The returned Socket is a new socket that
61      --  represents the server side of the connection. Server remains
62      --  available to receive further connections.
63      --
64      Accept_Socket (Server, Socket, Address);
65      --
66      --  Return a stream associated to the connected socket.
67      --
68      Channel := Stream (Socket);
69      --
70      --  Force Pong to block
71      --
72      delay 0.2;
73      --
74      --  Receive and print message from client Ping.
75      --
76      declare
77         Message : String := String'Input (Channel);
78      begin
79         Ada.Text_IO.Put_Line (Message);
80         --
81         --  Send same message to server Pong.
82         --
83         String'Output (Channel, Message);
84      end;
85
86      Close_Socket (Server);
87      Close_Socket (Socket);
88      --
89      --  Part of the multicast example
90      --
91      --  Create a datagram socket to send connectionless, unreliable
92      --  messages of a fixed maximum length.
93      --
94      Create_Socket (Socket, Family_Inet, Socket_Datagram);
95      --
96      --  Allow reuse of local addresses.
97      --
98      Set_Socket_Option
99        (Socket,
100         Socket_Level,
101         (Reuse_Address, True));
102      --
103      --  Join a multicast group.
104      --
105      Set_Socket_Option
106        (Socket,
107         IP_Protocol_For_IP_Level,
108         (Add_Membership, Inet_Addr (Group), Any_Inet_Addr));
109      --
110      --  Controls the live time of the datagram to avoid it being
111      --  looped forever due to routing errors. Routers decrement
112      --  the TTL of every datagram as it traverses from one network
113      --  to another and when its value reaches 0 the packet is
114      --  dropped. Default is 1.
115      --
116      Set_Socket_Option
117        (Socket,
118         IP_Protocol_For_IP_Level,
119         (Multicast_TTL, 1));
120      --
121      --  Want the data you send to be looped back to your host.
122      --
123      Set_Socket_Option
124        (Socket,
125         IP_Protocol_For_IP_Level,
126         (Multicast_Loop, True));
127      --
128      --  If this socket is intended to receive messages, bind it to a
129      --  given socket address.
130      --
131      Address.Addr := Any_Inet_Addr;
132      Address.Port := 55505;
133
134      Bind_Socket (Socket, Address);
135      --
136      --  If this socket is intended to send messages, provide the
137      --  receiver socket address.
138      --
139      Address.Addr := Inet_Addr (Group);
140      Address.Port := 55506;
141
142      Channel := Stream (Socket, Address);
143      --
144      --  Receive and print message from client Ping.
145      --
146      declare
147         Message : String := String'Input (Channel);
148
149      begin
150         --
151         --  Get the address of the sender.
152         --
153         Address := Get_Address (Channel);
154         Ada.Text_IO.Put_Line (Message & " from " & Image (Address));
155         --
156         --  Send same message to server Pong.
157         --
158         String'Output (Channel, Message);
159      end;
160
161      Close_Socket (Socket);
162
163      accept Stop;
164
165   exception when E : others =>
166      Ada.Text_IO.Put_Line
167        (Exception_Name (E) & ": " & Exception_Message (E));
168   end Pong;
169
170   task Ping is
171      entry Start;
172      entry Stop;
173   end Ping;
174
175   task body Ping is
176      Address  : Sock_Addr_Type;
177      Socket   : Socket_Type;
178      Channel  : Stream_Access;
179
180   begin
181      accept Start;
182   --
183   --  See comments in Ping section for the first steps.
184   --
185      Ada.Text_IO.Put_Line ("PING: Get_Host_By_Name" & Host_Name);
186      Address.Addr := Addresses (Get_Host_By_Name (Host_Name), 1);
187      Ada.Text_IO.Put_Line ("PING: Back from Get_Host_By_Name");
188      Address.Port := 5432;
189      Create_Socket (Socket);
190
191      Set_Socket_Option
192        (Socket,
193         Socket_Level,
194         (Reuse_Address, True));
195      --
196      --  Force Pong to block
197      --
198      delay 0.2;
199      --
200      --  If the client's socket is not bound, Connect_Socket will
201      --  bind to an unused address. The client uses Connect_Socket to
202      --  create a logical connection between the client's socket and
203      --  a server's socket returned by Accept_Socket.
204      --
205      Connect_Socket (Socket, Address);
206
207      Channel := Stream (Socket);
208      --
209      --  Send message to server Pong.
210      --
211      String'Output (Channel, "Hello world");
212      --
213      --  Force Ping to block
214      --
215      delay 0.2;
216      --
217      --  Receive and print message from server Pong.
218      --
219      Ada.Text_IO.Put_Line (String'Input (Channel));
220      Close_Socket (Socket);
221      --
222      --  Part of multicast example. Code similar to Pong's one.
223      --
224      Create_Socket (Socket, Family_Inet, Socket_Datagram);
225
226      Set_Socket_Option
227        (Socket,
228         Socket_Level,
229         (Reuse_Address, True));
230
231      Set_Socket_Option
232        (Socket,
233         IP_Protocol_For_IP_Level,
234         (Add_Membership, Inet_Addr (Group), Any_Inet_Addr));
235
236      Set_Socket_Option
237        (Socket,
238         IP_Protocol_For_IP_Level,
239         (Multicast_TTL, 1));
240
241      Set_Socket_Option
242        (Socket,
243         IP_Protocol_For_IP_Level,
244         (Multicast_Loop, True));
245
246      Address.Addr := Any_Inet_Addr;
247      Address.Port := 55506;
248
249      Bind_Socket (Socket, Address);
250
251      Address.Addr := Inet_Addr (Group);
252      Address.Port := 55505;
253
254      Channel := Stream (Socket, Address);
255      --
256      --  Send message to server Pong.
257      --
258      String'Output (Channel, "Hello world");
259      --
260      --  Receive and print message from server Pong.
261      --
262      declare
263         Message : String := String'Input (Channel);
264
265      begin
266         Address := Get_Address (Channel);
267         Ada.Text_IO.Put_Line (Message & " from " & Image (Address));
268      end;
269
270      Close_Socket (Socket);
271
272      accept Stop;
273
274   exception when E : others =>
275      Ada.Text_IO.Put_Line
276        (Exception_Name (E) & ": " & Exception_Message (E));
277   end Ping;
278   
279begin
280   --  Indicate whether the thread library provides process
281   --  blocking IO. Basically, if you are not using FSU threads
282   --  the default is ok.
283   --
284   Initialize (Process_Blocking_IO => False);
285   Ping.Start;
286   Pong.Start;
287   Ping.Stop;
288   Pong.Stop;
289   Finalize;
290end PingPong;
Note: See TracBrowser for help on using the repository browser.