source: ada-examples/pingpong/pingpong.adb @ 04eee9f

ada-examples-4-10-branch
Last change on this file since 04eee9f was 04eee9f, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 17, 2009 at 6:13:37 PM

2009-09-17 Joel Sherrill <joel.sherrill@…>

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