132
|
1 /*******************************************************************************
|
|
2
|
|
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved
|
|
4
|
|
5 license: BSD style: $(LICENSE)
|
|
6
|
|
7 version: Mar 2004 : Initial release
|
|
8 version: Dec 2006 : South Pacific release
|
|
9
|
|
10 author: Kris
|
|
11
|
|
12 *******************************************************************************/
|
|
13
|
|
14 module tango.net.DatagramConduit;
|
|
15
|
|
16 public import tango.io.Conduit;
|
|
17
|
|
18 package import tango.net.Socket,
|
|
19 tango.net.SocketConduit;
|
|
20
|
|
21 /*******************************************************************************
|
|
22
|
|
23 Datagrams provide a low-overhead, non-reliable data transmission
|
|
24 mechanism.
|
|
25
|
|
26 Datagrams are not 'connected' in the same manner as a TCP socket; you
|
|
27 don't need to listen() or accept() to receive a datagram, and data
|
|
28 may arrive from multiple sources. A datagram socket may, however,
|
|
29 still use the connect() method like a TCP socket. When connected,
|
|
30 the read() and write() methods will be restricted to a single address
|
|
31 rather than being open instead. That is, applying connect() will make
|
|
32 the address argument to both read() and write() irrelevant. Without
|
|
33 connect(), method write() must be supplied with an address and method
|
|
34 read() should be supplied with one to identify where data originated.
|
|
35
|
|
36 Note that when used as a listener, you must first bind the socket
|
|
37 to a local adapter. This can be achieved by binding the socket to
|
|
38 an InternetAddress constructed with a port only (ADDR_ANY), thus
|
|
39 requesting the OS to assign the address of a local network adapter
|
|
40
|
|
41 *******************************************************************************/
|
|
42
|
|
43 class DatagramConduit : SocketConduit
|
|
44 {
|
|
45 private Address to,
|
|
46 from;
|
|
47
|
|
48 /***********************************************************************
|
|
49
|
|
50 Create a read/write datagram socket
|
|
51
|
|
52 ***********************************************************************/
|
|
53
|
|
54 this ()
|
|
55 {
|
|
56 super (SocketType.DGRAM, ProtocolType.IP);
|
|
57 }
|
|
58
|
|
59 /***********************************************************************
|
|
60
|
|
61 Read bytes from an available datagram into the given array.
|
|
62 When provided, the 'from' address will be populated with the
|
|
63 origin of the incoming data. Note that we employ the timeout
|
|
64 mechanics exposed via our SocketConduit superclass.
|
|
65
|
|
66 Returns the number of bytes read from the input, or Eof if
|
|
67 the socket cannot read
|
|
68
|
|
69 ***********************************************************************/
|
|
70
|
|
71 uint read (void[] dst, Address from=null)
|
|
72 {
|
|
73 this.from = from;
|
|
74 return input.read (dst);
|
|
75 }
|
|
76
|
|
77 /***********************************************************************
|
|
78
|
|
79 Write an array to the specified address. If address 'to' is
|
|
80 null, it is assumed the socket has been connected instead.
|
|
81
|
|
82 Returns the number of bytes sent to the output, or Eof if
|
|
83 the socket cannot write
|
|
84
|
|
85 ***********************************************************************/
|
|
86
|
|
87 uint write (void[] src, Address to=null)
|
|
88 {
|
|
89 this.to = to;
|
|
90 return output.write (src);
|
|
91 }
|
|
92
|
|
93 /***********************************************************************
|
|
94
|
|
95 SocketConduit override:
|
|
96
|
|
97 Read available datagram bytes into a provided array. Returns
|
|
98 the number of bytes read from the input, or Eof if the socket
|
|
99 cannot read.
|
|
100
|
|
101 Note that we're taking advantage of timout support within the
|
|
102 superclass
|
|
103
|
|
104 ***********************************************************************/
|
|
105
|
|
106 protected override uint socketReader (void[] dst)
|
|
107 {
|
|
108 int count;
|
|
109
|
|
110 if (dst.length)
|
|
111 count = (from) ? socket.receiveFrom (dst, from) : socket.receiveFrom (dst);
|
|
112
|
|
113 return count;
|
|
114 }
|
|
115
|
|
116 /***********************************************************************
|
|
117
|
|
118 SocketConduit override:
|
|
119
|
|
120 Write the provided content to the socket. This will stall
|
|
121 until the socket responds in some manner. If there is no
|
|
122 target address held by this class, we assume the datagram
|
|
123 has been connected instead.
|
|
124
|
|
125 Returns the number of bytes sent to the output, or Eof if
|
|
126 the socket cannot write
|
|
127
|
|
128 ***********************************************************************/
|
|
129
|
|
130 protected override uint write (void[] src)
|
|
131 {
|
|
132 int count;
|
|
133
|
|
134 if (src.length)
|
|
135 {
|
|
136 count = (to) ? socket.sendTo (src, to) : socket.sendTo (src);
|
|
137 if (count <= 0)
|
|
138 count = Eof;
|
|
139 }
|
|
140 return count;
|
|
141 }
|
|
142 }
|
|
143
|
|
144
|
|
145
|
|
146 /******************************************************************************
|
|
147
|
|
148 *******************************************************************************/
|
|
149
|
|
150 debug (Datagram)
|
|
151 {
|
|
152 import tango.io.Console;
|
|
153
|
|
154 import tango.net.InternetAddress;
|
|
155
|
|
156 void main()
|
|
157 {
|
|
158 auto addr = new InternetAddress ("127.0.0.1", 8080);
|
|
159
|
|
160 // listen for datagrams on the local address
|
|
161 auto gram = new DatagramConduit;
|
|
162 gram.bind (addr);
|
|
163
|
|
164 // write to the local address
|
|
165 gram.write ("hello", addr);
|
|
166
|
|
167 // we are listening also ...
|
|
168 char[8] tmp;
|
|
169 auto x = new InternetAddress;
|
|
170 auto bytes = gram.read (tmp, x);
|
|
171 Cout (x) (tmp[0..bytes]).newline;
|
|
172 }
|
|
173 }
|