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