summaryrefslogtreecommitdiff
path: root/doc/html/SocketUDP_8cpp-source.htm
blob: 3268dba5e041fb8d9b8caaded99a9694da0e5541 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <title>SFML - Simple and Fast Multimedia Library</title>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
        <link href="doxygen.css" rel="stylesheet" type="text/css" />
        <link href="tabs.css" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <div id="logo">
            <img src="./logo.jpg" width="770" height="200" title="SFML home" alt="SFML logo" />
        </div>
<!-- Generated by Doxygen 1.5.8 -->
<div class="navigation" id="top">
  <div class="tabs">
    <ul>
      <li><a href="index.htm"><span>Main&nbsp;Page</span></a></li>
      <li><a href="namespaces.htm"><span>Namespaces</span></a></li>
      <li><a href="annotated.htm"><span>Classes</span></a></li>
      <li class="current"><a href="files.htm"><span>Files</span></a></li>
    </ul>
  </div>
  <div class="tabs">
    <ul>
      <li><a href="files.htm"><span>File&nbsp;List</span></a></li>
    </ul>
  </div>
<h1>SocketUDP.cpp</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 
<a name="l00002"></a>00002 <span class="comment">//</span>
<a name="l00003"></a>00003 <span class="comment">// SFML - Simple and Fast Multimedia Library</span>
<a name="l00004"></a>00004 <span class="comment">// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)</span>
<a name="l00005"></a>00005 <span class="comment">//</span>
<a name="l00006"></a>00006 <span class="comment">// This software is provided 'as-is', without any express or implied warranty.</span>
<a name="l00007"></a>00007 <span class="comment">// In no event will the authors be held liable for any damages arising from the use of this software.</span>
<a name="l00008"></a>00008 <span class="comment">//</span>
<a name="l00009"></a>00009 <span class="comment">// Permission is granted to anyone to use this software for any purpose,</span>
<a name="l00010"></a>00010 <span class="comment">// including commercial applications, and to alter it and redistribute it freely,</span>
<a name="l00011"></a>00011 <span class="comment">// subject to the following restrictions:</span>
<a name="l00012"></a>00012 <span class="comment">//</span>
<a name="l00013"></a>00013 <span class="comment">// 1. The origin of this software must not be misrepresented;</span>
<a name="l00014"></a>00014 <span class="comment">//    you must not claim that you wrote the original software.</span>
<a name="l00015"></a>00015 <span class="comment">//    If you use this software in a product, an acknowledgment</span>
<a name="l00016"></a>00016 <span class="comment">//    in the product documentation would be appreciated but is not required.</span>
<a name="l00017"></a>00017 <span class="comment">//</span>
<a name="l00018"></a>00018 <span class="comment">// 2. Altered source versions must be plainly marked as such,</span>
<a name="l00019"></a>00019 <span class="comment">//    and must not be misrepresented as being the original software.</span>
<a name="l00020"></a>00020 <span class="comment">//</span>
<a name="l00021"></a>00021 <span class="comment">// 3. This notice may not be removed or altered from any source distribution.</span>
<a name="l00022"></a>00022 <span class="comment">//</span>
<a name="l00024"></a>00024 <span class="comment"></span>
<a name="l00026"></a>00026 <span class="comment">// Headers</span>
<a name="l00028"></a>00028 <span class="comment"></span><span class="preprocessor">#include &lt;SFML/Network/SocketUDP.hpp&gt;</span>
<a name="l00029"></a>00029 <span class="preprocessor">#include &lt;SFML/Network/IPAddress.hpp&gt;</span>
<a name="l00030"></a>00030 <span class="preprocessor">#include &lt;SFML/Network/Packet.hpp&gt;</span>
<a name="l00031"></a>00031 <span class="preprocessor">#include &lt;algorithm&gt;</span>
<a name="l00032"></a>00032 <span class="preprocessor">#include &lt;iostream&gt;</span>
<a name="l00033"></a>00033 <span class="preprocessor">#include &lt;string.h&gt;</span>
<a name="l00034"></a>00034 
<a name="l00035"></a>00035 
<a name="l00036"></a>00036 <span class="keyword">namespace </span>sf
<a name="l00037"></a>00037 {
<a name="l00041"></a><a class="code" href="classsf_1_1SocketUDP.htm#844e648922eccd86d4815d19472bb901">00041</a> <a class="code" href="classsf_1_1SocketUDP.htm#844e648922eccd86d4815d19472bb901" title="Default constructor.">SocketUDP::SocketUDP</a>()
<a name="l00042"></a>00042 {
<a name="l00043"></a>00043     Create();
<a name="l00044"></a>00044 }
<a name="l00045"></a>00045 
<a name="l00046"></a>00046 
<a name="l00050"></a><a class="code" href="classsf_1_1SocketUDP.htm#128ebfff7472dfdd330b46b719e06fd6">00050</a> <span class="keywordtype">void</span> <a class="code" href="classsf_1_1SocketUDP.htm#128ebfff7472dfdd330b46b719e06fd6" title="Change the blocking state of the socket.">SocketUDP::SetBlocking</a>(<span class="keywordtype">bool</span> Blocking)
<a name="l00051"></a>00051 {
<a name="l00052"></a>00052     <span class="comment">// Make sure our socket is valid</span>
<a name="l00053"></a>00053     <span class="keywordflow">if</span> (!<a class="code" href="classsf_1_1SocketUDP.htm#ffecb97b84b51dea691934f9195abc1f" title="Check if the socket is in a valid state ; this function can be called any time to...">IsValid</a>())
<a name="l00054"></a>00054         Create();
<a name="l00055"></a>00055 
<a name="l00056"></a>00056     <a class="code" href="classsf_1_1SocketUDP.htm#128ebfff7472dfdd330b46b719e06fd6" title="Change the blocking state of the socket.">SocketHelper::SetBlocking</a>(mySocket, Blocking);
<a name="l00057"></a>00057     myIsBlocking = Blocking;
<a name="l00058"></a>00058 }
<a name="l00059"></a>00059 
<a name="l00060"></a>00060 
<a name="l00064"></a><a class="code" href="classsf_1_1SocketUDP.htm#4a7e364fd39aa7338f0822d849323a5d">00064</a> <span class="keywordtype">bool</span> <a class="code" href="classsf_1_1SocketUDP.htm#4a7e364fd39aa7338f0822d849323a5d" title="Bind the socket to a specific port.">SocketUDP::Bind</a>(<span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> Port)
<a name="l00065"></a>00065 {
<a name="l00066"></a>00066     <span class="comment">// Check if the socket is already bound to the specified port</span>
<a name="l00067"></a>00067     <span class="keywordflow">if</span> (myPort != Port)
<a name="l00068"></a>00068     {
<a name="l00069"></a>00069         <span class="comment">// If the socket was previously bound to another port, we need to unbind it first</span>
<a name="l00070"></a>00070         <a class="code" href="classsf_1_1SocketUDP.htm#6f6b448b8ab63913dad5d6906645081c" title="Unbind the socket from its previous port, if any.">Unbind</a>();
<a name="l00071"></a>00071 
<a name="l00072"></a>00072         <span class="keywordflow">if</span> (Port != 0)
<a name="l00073"></a>00073         {
<a name="l00074"></a>00074             <span class="comment">// Build an address with the specified port</span>
<a name="l00075"></a>00075             sockaddr_in Addr;
<a name="l00076"></a>00076             Addr.sin_family      = AF_INET;
<a name="l00077"></a>00077             Addr.sin_port        = htons(Port);
<a name="l00078"></a>00078             Addr.sin_addr.s_addr = INADDR_ANY;
<a name="l00079"></a>00079             memset(Addr.sin_zero, 0, <span class="keyword">sizeof</span>(Addr.sin_zero));
<a name="l00080"></a>00080 
<a name="l00081"></a>00081             <span class="comment">// Bind the socket to the port</span>
<a name="l00082"></a>00082             <span class="keywordflow">if</span> (bind(mySocket, reinterpret_cast&lt;sockaddr*&gt;(&amp;Addr), <span class="keyword">sizeof</span>(Addr)) == -1)
<a name="l00083"></a>00083             {
<a name="l00084"></a>00084                 std::cerr &lt;&lt; <span class="stringliteral">"Failed to bind the socket to port "</span> &lt;&lt; Port &lt;&lt; std::endl;
<a name="l00085"></a>00085                 myPort = 0;
<a name="l00086"></a>00086                 <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00087"></a>00087             }
<a name="l00088"></a>00088         }
<a name="l00089"></a>00089 
<a name="l00090"></a>00090         <span class="comment">// Save the new port</span>
<a name="l00091"></a>00091         myPort = Port;
<a name="l00092"></a>00092     }
<a name="l00093"></a>00093 
<a name="l00094"></a>00094     <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00095"></a>00095 }
<a name="l00096"></a>00096 
<a name="l00097"></a>00097 
<a name="l00101"></a><a class="code" href="classsf_1_1SocketUDP.htm#6f6b448b8ab63913dad5d6906645081c">00101</a> <span class="keywordtype">bool</span> <a class="code" href="classsf_1_1SocketUDP.htm#6f6b448b8ab63913dad5d6906645081c" title="Unbind the socket from its previous port, if any.">SocketUDP::Unbind</a>()
<a name="l00102"></a>00102 {
<a name="l00103"></a>00103     <span class="comment">// To unbind the socket, we just recreate it</span>
<a name="l00104"></a>00104     <span class="keywordflow">if</span> (myPort != 0)
<a name="l00105"></a>00105     {
<a name="l00106"></a>00106         <a class="code" href="classsf_1_1SocketUDP.htm#c9abf54c9ced16b55ddef46973cd1a58" title="Close the socket.">Close</a>();
<a name="l00107"></a>00107         Create();
<a name="l00108"></a>00108         myPort = 0;
<a name="l00109"></a>00109     }
<a name="l00110"></a>00110 
<a name="l00111"></a>00111     <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00112"></a>00112 }
<a name="l00113"></a>00113 
<a name="l00114"></a>00114 
<a name="l00118"></a><a class="code" href="classsf_1_1SocketUDP.htm#bce9f533dd86c0fd8fbe26b7efce3bc2">00118</a> Socket::Status <a class="code" href="classsf_1_1SocketUDP.htm#bce9f533dd86c0fd8fbe26b7efce3bc2" title="Send an array of bytes.">SocketUDP::Send</a>(<span class="keyword">const</span> <span class="keywordtype">char</span>* Data, std::size_t Size, <span class="keyword">const</span> <a class="code" href="classsf_1_1IPAddress.htm" title="IPAddress provides easy manipulation of IP v4 addresses.">IPAddress</a>&amp; Address, <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> Port)
<a name="l00119"></a>00119 {
<a name="l00120"></a>00120     <span class="comment">// Make sure the socket is valid</span>
<a name="l00121"></a>00121     <span class="keywordflow">if</span> (!<a class="code" href="classsf_1_1SocketUDP.htm#ffecb97b84b51dea691934f9195abc1f" title="Check if the socket is in a valid state ; this function can be called any time to...">IsValid</a>())
<a name="l00122"></a>00122         Create();
<a name="l00123"></a>00123 
<a name="l00124"></a>00124     <span class="comment">// Check parameters</span>
<a name="l00125"></a>00125     <span class="keywordflow">if</span> (Data &amp;&amp; Size)
<a name="l00126"></a>00126     {
<a name="l00127"></a>00127         <span class="comment">// Build the target address</span>
<a name="l00128"></a>00128         sockaddr_in Target;
<a name="l00129"></a>00129         Target.sin_family      = AF_INET;
<a name="l00130"></a>00130         Target.sin_port        = htons(Port);
<a name="l00131"></a>00131         Target.sin_addr.s_addr = inet_addr(Address.<a class="code" href="classsf_1_1IPAddress.htm#76eadca85be545b5c1c68a4d0dc1c643" title="Get a string representation of the address.">ToString</a>().c_str());
<a name="l00132"></a>00132         memset(Target.sin_zero, 0, <span class="keyword">sizeof</span>(Target.sin_zero));
<a name="l00133"></a>00133 
<a name="l00134"></a>00134         <span class="comment">// Loop until every byte has been sent</span>
<a name="l00135"></a>00135         <span class="keywordtype">int</span> Sent = 0;
<a name="l00136"></a>00136         <span class="keywordtype">int</span> SizeToSend = <span class="keyword">static_cast&lt;</span><span class="keywordtype">int</span><span class="keyword">&gt;</span>(Size);
<a name="l00137"></a>00137         <span class="keywordflow">for</span> (<span class="keywordtype">int</span> Length = 0; Length &lt; SizeToSend; Length += Sent)
<a name="l00138"></a>00138         {
<a name="l00139"></a>00139             <span class="comment">// Send a chunk of data</span>
<a name="l00140"></a>00140             Sent = sendto(mySocket, Data + Length, SizeToSend - Length, 0, reinterpret_cast&lt;sockaddr*&gt;(&amp;Target), <span class="keyword">sizeof</span>(Target));
<a name="l00141"></a>00141 
<a name="l00142"></a>00142             <span class="comment">// Check errors</span>
<a name="l00143"></a>00143             <span class="keywordflow">if</span> (Sent &lt;= 0)
<a name="l00144"></a>00144                 <span class="keywordflow">return</span> <a class="code" href="classsf_1_1SocketHelper.htm#7e634801c53a5a1b2ee16757e2d96a83" title="Get the last socket error status.">SocketHelper::GetErrorStatus</a>();
<a name="l00145"></a>00145         }
<a name="l00146"></a>00146 
<a name="l00147"></a>00147         <span class="keywordflow">return</span> Socket::Done;
<a name="l00148"></a>00148     }
<a name="l00149"></a>00149     <span class="keywordflow">else</span>
<a name="l00150"></a>00150     {
<a name="l00151"></a>00151         <span class="comment">// Error...</span>
<a name="l00152"></a>00152         std::cerr &lt;&lt; <span class="stringliteral">"Cannot send data over the network (invalid parameters)"</span> &lt;&lt; std::endl;
<a name="l00153"></a>00153         <span class="keywordflow">return</span> Socket::Error;
<a name="l00154"></a>00154     }
<a name="l00155"></a>00155 }
<a name="l00156"></a>00156 
<a name="l00157"></a>00157 
<a name="l00162"></a><a class="code" href="classsf_1_1SocketUDP.htm#c6928928fa1d6242db1f8d4176369996">00162</a> Socket::Status <a class="code" href="classsf_1_1SocketUDP.htm#c6928928fa1d6242db1f8d4176369996" title="Receive an array of bytes.">SocketUDP::Receive</a>(<span class="keywordtype">char</span>* Data, std::size_t MaxSize, std::size_t&amp; SizeReceived, <a class="code" href="classsf_1_1IPAddress.htm" title="IPAddress provides easy manipulation of IP v4 addresses.">IPAddress</a>&amp; Address, <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span>&amp; Port)
<a name="l00163"></a>00163 {
<a name="l00164"></a>00164     <span class="comment">// First clear the size received</span>
<a name="l00165"></a>00165     SizeReceived = 0;
<a name="l00166"></a>00166 
<a name="l00167"></a>00167     <span class="comment">// Make sure the socket is bound to a port</span>
<a name="l00168"></a>00168     <span class="keywordflow">if</span> (myPort == 0)
<a name="l00169"></a>00169     {
<a name="l00170"></a>00170         std::cerr &lt;&lt; <span class="stringliteral">"Failed to receive data ; the UDP socket first needs to be bound to a port"</span> &lt;&lt; std::endl;
<a name="l00171"></a>00171         <span class="keywordflow">return</span> Socket::Error;
<a name="l00172"></a>00172     }
<a name="l00173"></a>00173 
<a name="l00174"></a>00174     <span class="comment">// Make sure the socket is valid</span>
<a name="l00175"></a>00175     <span class="keywordflow">if</span> (!<a class="code" href="classsf_1_1SocketUDP.htm#ffecb97b84b51dea691934f9195abc1f" title="Check if the socket is in a valid state ; this function can be called any time to...">IsValid</a>())
<a name="l00176"></a>00176         Create();
<a name="l00177"></a>00177 
<a name="l00178"></a>00178     <span class="comment">// Check parameters</span>
<a name="l00179"></a>00179     <span class="keywordflow">if</span> (Data &amp;&amp; MaxSize)
<a name="l00180"></a>00180     {
<a name="l00181"></a>00181         <span class="comment">// Data that will be filled with the other computer's address</span>
<a name="l00182"></a>00182         sockaddr_in Sender;
<a name="l00183"></a>00183         Sender.sin_family      = AF_INET;
<a name="l00184"></a>00184         Sender.sin_port        = 0;
<a name="l00185"></a>00185         Sender.sin_addr.s_addr = INADDR_ANY;
<a name="l00186"></a>00186         memset(Sender.sin_zero, 0, <span class="keyword">sizeof</span>(Sender.sin_zero));
<a name="l00187"></a>00187         SocketHelper::LengthType SenderSize = <span class="keyword">sizeof</span>(Sender);
<a name="l00188"></a>00188 
<a name="l00189"></a>00189         <span class="comment">// Receive a chunk of bytes</span>
<a name="l00190"></a>00190         <span class="keywordtype">int</span> Received = recvfrom(mySocket, Data, static_cast&lt;int&gt;(MaxSize), 0, reinterpret_cast&lt;sockaddr*&gt;(&amp;Sender), &amp;SenderSize);
<a name="l00191"></a>00191 
<a name="l00192"></a>00192         <span class="comment">// Check the number of bytes received</span>
<a name="l00193"></a>00193         <span class="keywordflow">if</span> (Received &gt; 0)
<a name="l00194"></a>00194         {
<a name="l00195"></a>00195             Address = <a class="code" href="classsf_1_1IPAddress.htm" title="IPAddress provides easy manipulation of IP v4 addresses.">IPAddress</a>(inet_ntoa(Sender.sin_addr));
<a name="l00196"></a>00196             Port = ntohs(Sender.sin_port);
<a name="l00197"></a>00197             SizeReceived = <span class="keyword">static_cast&lt;</span>std::size_t<span class="keyword">&gt;</span>(Received);
<a name="l00198"></a>00198             <span class="keywordflow">return</span> Socket::Done;
<a name="l00199"></a>00199         }
<a name="l00200"></a>00200         <span class="keywordflow">else</span>
<a name="l00201"></a>00201         {
<a name="l00202"></a>00202             Address = <a class="code" href="classsf_1_1IPAddress.htm" title="IPAddress provides easy manipulation of IP v4 addresses.">IPAddress</a>();
<a name="l00203"></a>00203             Port = 0;
<a name="l00204"></a>00204             <span class="keywordflow">return</span> Received == 0 ? Socket::Disconnected : <a class="code" href="classsf_1_1SocketHelper.htm#7e634801c53a5a1b2ee16757e2d96a83" title="Get the last socket error status.">SocketHelper::GetErrorStatus</a>();
<a name="l00205"></a>00205         }
<a name="l00206"></a>00206     }
<a name="l00207"></a>00207     <span class="keywordflow">else</span>
<a name="l00208"></a>00208     {
<a name="l00209"></a>00209         <span class="comment">// Error...</span>
<a name="l00210"></a>00210         std::cerr &lt;&lt; <span class="stringliteral">"Cannot receive data from the network (invalid parameters)"</span> &lt;&lt; std::endl;
<a name="l00211"></a>00211         <span class="keywordflow">return</span> Socket::Error;
<a name="l00212"></a>00212     }
<a name="l00213"></a>00213 }
<a name="l00214"></a>00214 
<a name="l00215"></a>00215 
<a name="l00219"></a><a class="code" href="classsf_1_1SocketUDP.htm#fef698f2544ac0364d422e1e1ba7a5b6">00219</a> Socket::Status <a class="code" href="classsf_1_1SocketUDP.htm#bce9f533dd86c0fd8fbe26b7efce3bc2" title="Send an array of bytes.">SocketUDP::Send</a>(<a class="code" href="classsf_1_1Packet.htm" title="Packet wraps data to send / to receive through the network.">Packet</a>&amp; PacketToSend, <span class="keyword">const</span> <a class="code" href="classsf_1_1IPAddress.htm" title="IPAddress provides easy manipulation of IP v4 addresses.">IPAddress</a>&amp; Address, <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> Port)
<a name="l00220"></a>00220 {
<a name="l00221"></a>00221     <span class="comment">// Get the data to send from the packet</span>
<a name="l00222"></a>00222     std::size_t DataSize = 0;
<a name="l00223"></a>00223     <span class="keyword">const</span> <span class="keywordtype">char</span>* Data = PacketToSend.<a class="code" href="classsf_1_1Packet.htm#f7572423964fc3baf9ca9fe1e5a28993" title="Called before the packet is sent to the network.">OnSend</a>(DataSize);
<a name="l00224"></a>00224 
<a name="l00225"></a>00225     <span class="comment">// Send the packet size</span>
<a name="l00226"></a>00226     Uint32 PacketSize = htonl(static_cast&lt;unsigned long&gt;(DataSize));
<a name="l00227"></a>00227     <a class="code" href="classsf_1_1SocketUDP.htm#bce9f533dd86c0fd8fbe26b7efce3bc2" title="Send an array of bytes.">Send</a>(reinterpret_cast&lt;const char*&gt;(&amp;PacketSize), <span class="keyword">sizeof</span>(PacketSize), Address, Port);
<a name="l00228"></a>00228 
<a name="l00229"></a>00229     <span class="comment">// Send the packet data</span>
<a name="l00230"></a>00230     <span class="keywordflow">if</span> (PacketSize &gt; 0)
<a name="l00231"></a>00231     {
<a name="l00232"></a>00232         <span class="keywordflow">return</span> <a class="code" href="classsf_1_1SocketUDP.htm#bce9f533dd86c0fd8fbe26b7efce3bc2" title="Send an array of bytes.">Send</a>(Data, DataSize, Address, Port);
<a name="l00233"></a>00233     }
<a name="l00234"></a>00234     <span class="keywordflow">else</span>
<a name="l00235"></a>00235     {
<a name="l00236"></a>00236         <span class="keywordflow">return</span> Socket::Done;
<a name="l00237"></a>00237     }
<a name="l00238"></a>00238 }
<a name="l00239"></a>00239 
<a name="l00240"></a>00240 
<a name="l00245"></a><a class="code" href="classsf_1_1SocketUDP.htm#463bbd635513f2653f072c2f220d2495">00245</a> Socket::Status <a class="code" href="classsf_1_1SocketUDP.htm#c6928928fa1d6242db1f8d4176369996" title="Receive an array of bytes.">SocketUDP::Receive</a>(<a class="code" href="classsf_1_1Packet.htm" title="Packet wraps data to send / to receive through the network.">Packet</a>&amp; PacketToReceive, <a class="code" href="classsf_1_1IPAddress.htm" title="IPAddress provides easy manipulation of IP v4 addresses.">IPAddress</a>&amp; Address, <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span>&amp; Port)
<a name="l00246"></a>00246 {
<a name="l00247"></a>00247     <span class="comment">// We start by getting the size of the incoming packet</span>
<a name="l00248"></a>00248     Uint32      PacketSize = 0;
<a name="l00249"></a>00249     std::size_t Received   = 0;
<a name="l00250"></a>00250     <span class="keywordflow">if</span> (myPendingPacketSize &lt; 0)
<a name="l00251"></a>00251     {
<a name="l00252"></a>00252         <span class="comment">// Loop until we've received the entire size of the packet</span>
<a name="l00253"></a>00253         <span class="comment">// (even a 4 bytes variable may be received in more than one call)</span>
<a name="l00254"></a>00254         <span class="keywordflow">while</span> (myPendingHeaderSize &lt; <span class="keyword">sizeof</span>(myPendingHeader))
<a name="l00255"></a>00255         {
<a name="l00256"></a>00256             <span class="keywordtype">char</span>* Data = <span class="keyword">reinterpret_cast&lt;</span><span class="keywordtype">char</span>*<span class="keyword">&gt;</span>(&amp;myPendingHeader) + myPendingHeaderSize;
<a name="l00257"></a>00257             Socket::Status Status = <a class="code" href="classsf_1_1SocketUDP.htm#c6928928fa1d6242db1f8d4176369996" title="Receive an array of bytes.">Receive</a>(Data, <span class="keyword">sizeof</span>(myPendingHeader) - myPendingHeaderSize, Received, Address, Port);
<a name="l00258"></a>00258             myPendingHeaderSize += Received;
<a name="l00259"></a>00259 
<a name="l00260"></a>00260             <span class="keywordflow">if</span> (Status != Socket::Done)
<a name="l00261"></a>00261                 <span class="keywordflow">return</span> Status;
<a name="l00262"></a>00262         }
<a name="l00263"></a>00263 
<a name="l00264"></a>00264         PacketSize = ntohl(myPendingHeader);
<a name="l00265"></a>00265         myPendingHeaderSize = 0;
<a name="l00266"></a>00266     }
<a name="l00267"></a>00267     <span class="keywordflow">else</span>
<a name="l00268"></a>00268     {
<a name="l00269"></a>00269         <span class="comment">// There is a pending packet : we already know its size</span>
<a name="l00270"></a>00270         PacketSize = myPendingPacketSize;
<a name="l00271"></a>00271     }
<a name="l00272"></a>00272 
<a name="l00273"></a>00273     <span class="comment">// Use another address instance for receiving the packet data ;</span>
<a name="l00274"></a>00274     <span class="comment">// chunks of data coming from a different sender will be discarded (and lost...)</span>
<a name="l00275"></a>00275     <a class="code" href="classsf_1_1IPAddress.htm" title="IPAddress provides easy manipulation of IP v4 addresses.">IPAddress</a> Sender;
<a name="l00276"></a>00276     <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> SenderPort;
<a name="l00277"></a>00277 
<a name="l00278"></a>00278     <span class="comment">// Then loop until we receive all the packet data</span>
<a name="l00279"></a>00279     <span class="keywordtype">char</span> Buffer[1024];
<a name="l00280"></a>00280     <span class="keywordflow">while</span> (myPendingPacket.size() &lt; PacketSize)
<a name="l00281"></a>00281     {
<a name="l00282"></a>00282         <span class="comment">// Receive a chunk of data</span>
<a name="l00283"></a>00283         std::size_t SizeToGet = std::min(static_cast&lt;std::size_t&gt;(PacketSize - myPendingPacket.size()), <span class="keyword">sizeof</span>(Buffer));
<a name="l00284"></a>00284         Socket::Status Status = <a class="code" href="classsf_1_1SocketUDP.htm#c6928928fa1d6242db1f8d4176369996" title="Receive an array of bytes.">Receive</a>(Buffer, SizeToGet, Received, Sender, SenderPort);
<a name="l00285"></a>00285         <span class="keywordflow">if</span> (Status != Socket::Done)
<a name="l00286"></a>00286         {
<a name="l00287"></a>00287             <span class="comment">// We must save the size of the pending packet until we can receive its content</span>
<a name="l00288"></a>00288             <span class="keywordflow">if</span> (Status == Socket::NotReady)
<a name="l00289"></a>00289                 myPendingPacketSize = PacketSize;
<a name="l00290"></a>00290             <span class="keywordflow">return</span> Status;
<a name="l00291"></a>00291         }
<a name="l00292"></a>00292 
<a name="l00293"></a>00293         <span class="comment">// Append it into the packet</span>
<a name="l00294"></a>00294         <span class="keywordflow">if</span> ((Sender == Address) &amp;&amp; (SenderPort == Port) &amp;&amp; (Received &gt; 0))
<a name="l00295"></a>00295         {
<a name="l00296"></a>00296             myPendingPacket.resize(myPendingPacket.size() + Received);
<a name="l00297"></a>00297             <span class="keywordtype">char</span>* Begin = &amp;myPendingPacket[0] + myPendingPacket.size() - Received;
<a name="l00298"></a>00298             memcpy(Begin, Buffer, Received);
<a name="l00299"></a>00299         }
<a name="l00300"></a>00300     }
<a name="l00301"></a>00301 
<a name="l00302"></a>00302     <span class="comment">// We have received all the datas : we can copy it to the user packet, and clear our internal packet</span>
<a name="l00303"></a>00303     PacketToReceive.<a class="code" href="classsf_1_1Packet.htm#3a7a30fb7a39e59df0cbd773756f60da" title="Clear the packet data.">Clear</a>();
<a name="l00304"></a>00304     <span class="keywordflow">if</span> (!myPendingPacket.empty())
<a name="l00305"></a>00305         PacketToReceive.<a class="code" href="classsf_1_1Packet.htm#9a480468cc7745863b7c93e0ae449cbd" title="Called after the packet has been received from the network.">OnReceive</a>(&amp;myPendingPacket[0], myPendingPacket.size());
<a name="l00306"></a>00306     myPendingPacket.clear();
<a name="l00307"></a>00307     myPendingPacketSize = -1;
<a name="l00308"></a>00308 
<a name="l00309"></a>00309     <span class="keywordflow">return</span> Socket::Done;
<a name="l00310"></a>00310 }
<a name="l00311"></a>00311 
<a name="l00312"></a>00312 
<a name="l00316"></a><a class="code" href="classsf_1_1SocketUDP.htm#c9abf54c9ced16b55ddef46973cd1a58">00316</a> <span class="keywordtype">bool</span> <a class="code" href="classsf_1_1SocketUDP.htm#c9abf54c9ced16b55ddef46973cd1a58" title="Close the socket.">SocketUDP::Close</a>()
<a name="l00317"></a>00317 {
<a name="l00318"></a>00318     <span class="keywordflow">if</span> (<a class="code" href="classsf_1_1SocketUDP.htm#ffecb97b84b51dea691934f9195abc1f" title="Check if the socket is in a valid state ; this function can be called any time to...">IsValid</a>())
<a name="l00319"></a>00319     {
<a name="l00320"></a>00320         <span class="keywordflow">if</span> (!<a class="code" href="classsf_1_1SocketHelper.htm#ec266cafe3270d1f2e210909b9b6d232" title="Close / destroy a socket.">SocketHelper::Close</a>(mySocket))
<a name="l00321"></a>00321         {
<a name="l00322"></a>00322             std::cerr &lt;&lt; <span class="stringliteral">"Failed to close socket"</span> &lt;&lt; std::endl;
<a name="l00323"></a>00323             <span class="keywordflow">return</span> <span class="keyword">false</span>;
<a name="l00324"></a>00324         }
<a name="l00325"></a>00325 
<a name="l00326"></a>00326         mySocket = <a class="code" href="classsf_1_1SocketHelper.htm#99e426a217cc8847264f837632b4e458" title="Return the value of the invalid socket.">SocketHelper::InvalidSocket</a>();
<a name="l00327"></a>00327     }
<a name="l00328"></a>00328 
<a name="l00329"></a>00329     myPort       = 0;
<a name="l00330"></a>00330     myIsBlocking = <span class="keyword">true</span>;
<a name="l00331"></a>00331 
<a name="l00332"></a>00332     <span class="keywordflow">return</span> <span class="keyword">true</span>;
<a name="l00333"></a>00333 }
<a name="l00334"></a>00334 
<a name="l00335"></a>00335 
<a name="l00340"></a><a class="code" href="classsf_1_1SocketUDP.htm#ffecb97b84b51dea691934f9195abc1f">00340</a> <span class="keywordtype">bool</span> <a class="code" href="classsf_1_1SocketUDP.htm#ffecb97b84b51dea691934f9195abc1f" title="Check if the socket is in a valid state ; this function can be called any time to...">SocketUDP::IsValid</a>()<span class="keyword"> const</span>
<a name="l00341"></a>00341 <span class="keyword"></span>{
<a name="l00342"></a>00342     <span class="keywordflow">return</span> mySocket != <a class="code" href="classsf_1_1SocketHelper.htm#99e426a217cc8847264f837632b4e458" title="Return the value of the invalid socket.">SocketHelper::InvalidSocket</a>();
<a name="l00343"></a>00343 }
<a name="l00344"></a>00344 
<a name="l00345"></a>00345 
<a name="l00349"></a><a class="code" href="classsf_1_1SocketUDP.htm#14f2c68a57a163a5d142acd0c4b022dd">00349</a> <span class="keywordtype">unsigned</span> <span class="keywordtype">short</span> <a class="code" href="classsf_1_1SocketUDP.htm#14f2c68a57a163a5d142acd0c4b022dd" title="Get the port the socket is currently bound to.">SocketUDP::GetPort</a>()<span class="keyword"> const</span>
<a name="l00350"></a>00350 <span class="keyword"></span>{
<a name="l00351"></a>00351     <span class="keywordflow">return</span> myPort;
<a name="l00352"></a>00352 }
<a name="l00353"></a>00353 
<a name="l00354"></a>00354 
<a name="l00358"></a><a class="code" href="classsf_1_1SocketUDP.htm#5e6df73d3b4acf5890bd48229b2d2fa0">00358</a> <span class="keywordtype">bool</span> <a class="code" href="classsf_1_1SocketUDP.htm#5e6df73d3b4acf5890bd48229b2d2fa0" title="Comparison operator ==.">SocketUDP::operator ==</a>(<span class="keyword">const</span> <a class="code" href="classsf_1_1SocketUDP.htm" title="SocketUDP wraps a socket using UDP protocol to send data fastly (but with less safety)...">SocketUDP</a>&amp; Other)<span class="keyword"> const</span>
<a name="l00359"></a>00359 <span class="keyword"></span>{
<a name="l00360"></a>00360     <span class="keywordflow">return</span> mySocket == Other.<a class="code" href="classsf_1_1SocketUDP.htm#95874e9b7b37724e82820b02b8e4a12a" title="Socket identifier.">mySocket</a>;
<a name="l00361"></a>00361 }
<a name="l00362"></a>00362 
<a name="l00363"></a>00363 
<a name="l00367"></a><a class="code" href="classsf_1_1SocketUDP.htm#2cb8111d79d32e456f047132e61acd24">00367</a> <span class="keywordtype">bool</span> <a class="code" href="classsf_1_1SocketUDP.htm#2cb8111d79d32e456f047132e61acd24" title="Comparison operator !=.">SocketUDP::operator !=</a>(<span class="keyword">const</span> <a class="code" href="classsf_1_1SocketUDP.htm" title="SocketUDP wraps a socket using UDP protocol to send data fastly (but with less safety)...">SocketUDP</a>&amp; Other)<span class="keyword"> const</span>
<a name="l00368"></a>00368 <span class="keyword"></span>{
<a name="l00369"></a>00369     <span class="keywordflow">return</span> mySocket != Other.<a class="code" href="classsf_1_1SocketUDP.htm#95874e9b7b37724e82820b02b8e4a12a" title="Socket identifier.">mySocket</a>;
<a name="l00370"></a>00370 }
<a name="l00371"></a>00371 
<a name="l00372"></a>00372 
<a name="l00378"></a><a class="code" href="classsf_1_1SocketUDP.htm#fc35043831c10528cc3e97b959438b95">00378</a> <span class="keywordtype">bool</span> <a class="code" href="classsf_1_1SocketUDP.htm#fc35043831c10528cc3e97b959438b95" title="Comparison operator &amp;lt;.">SocketUDP::operator &lt;</a>(<span class="keyword">const</span> <a class="code" href="classsf_1_1SocketUDP.htm" title="SocketUDP wraps a socket using UDP protocol to send data fastly (but with less safety)...">SocketUDP</a>&amp; Other)<span class="keyword"> const</span>
<a name="l00379"></a>00379 <span class="keyword"></span>{
<a name="l00380"></a>00380     <span class="keywordflow">return</span> mySocket &lt; Other.<a class="code" href="classsf_1_1SocketUDP.htm#95874e9b7b37724e82820b02b8e4a12a" title="Socket identifier.">mySocket</a>;
<a name="l00381"></a>00381 }
<a name="l00382"></a>00382 
<a name="l00383"></a>00383 
<a name="l00388"></a>00388 <a class="code" href="classsf_1_1SocketUDP.htm#844e648922eccd86d4815d19472bb901" title="Default constructor.">SocketUDP::SocketUDP</a>(SocketHelper::SocketType Descriptor)
<a name="l00389"></a>00389 {
<a name="l00390"></a>00390     Create(Descriptor);
<a name="l00391"></a>00391 }
<a name="l00392"></a>00392 
<a name="l00393"></a>00393 
<a name="l00397"></a>00397 <span class="keywordtype">void</span> SocketUDP::Create(SocketHelper::SocketType Descriptor)
<a name="l00398"></a>00398 {
<a name="l00399"></a>00399     <span class="comment">// Use the given socket descriptor, or get a new one</span>
<a name="l00400"></a>00400     mySocket = Descriptor ? Descriptor : socket(PF_INET, SOCK_DGRAM, 0);
<a name="l00401"></a>00401     myIsBlocking = <span class="keyword">true</span>;
<a name="l00402"></a>00402 
<a name="l00403"></a>00403     <span class="comment">// Clear the last port used</span>
<a name="l00404"></a>00404     myPort = 0;
<a name="l00405"></a>00405 
<a name="l00406"></a>00406     <span class="comment">// Reset the pending packet</span>
<a name="l00407"></a>00407     myPendingHeaderSize = 0;
<a name="l00408"></a>00408     myPendingPacket.clear();
<a name="l00409"></a>00409     myPendingPacketSize = -1;
<a name="l00410"></a>00410 
<a name="l00411"></a>00411     <span class="comment">// Setup default options</span>
<a name="l00412"></a>00412     <span class="keywordflow">if</span> (<a class="code" href="classsf_1_1SocketUDP.htm#ffecb97b84b51dea691934f9195abc1f" title="Check if the socket is in a valid state ; this function can be called any time to...">IsValid</a>())
<a name="l00413"></a>00413     {
<a name="l00414"></a>00414         <span class="comment">// To avoid the "Address already in use" error message when trying to bind to the same port</span>
<a name="l00415"></a>00415         <span class="keywordtype">int</span> Yes = 1;
<a name="l00416"></a>00416         <span class="keywordflow">if</span> (setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast&lt;char*&gt;(&amp;Yes), <span class="keyword">sizeof</span>(Yes)) == -1)
<a name="l00417"></a>00417         {
<a name="l00418"></a>00418             std::cerr &lt;&lt; <span class="stringliteral">"Failed to set socket option \"reuse address\" ; "</span>
<a name="l00419"></a>00419                       &lt;&lt; <span class="stringliteral">"binding to a same port may fail if too fast"</span> &lt;&lt; std::endl;
<a name="l00420"></a>00420         }
<a name="l00421"></a>00421 
<a name="l00422"></a>00422         <span class="comment">// Enable broadcast by default</span>
<a name="l00423"></a>00423         <span class="keywordflow">if</span> (setsockopt(mySocket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast&lt;char*&gt;(&amp;Yes), <span class="keyword">sizeof</span>(Yes)) == -1)
<a name="l00424"></a>00424         {
<a name="l00425"></a>00425             std::cerr &lt;&lt; <span class="stringliteral">"Failed to enable broadcast on UDP socket"</span> &lt;&lt; std::endl;
<a name="l00426"></a>00426         }
<a name="l00427"></a>00427 
<a name="l00428"></a>00428         <span class="comment">// Set blocking by default (should always be the case anyway)</span>
<a name="l00429"></a>00429         <a class="code" href="classsf_1_1SocketUDP.htm#128ebfff7472dfdd330b46b719e06fd6" title="Change the blocking state of the socket.">SetBlocking</a>(<span class="keyword">true</span>);
<a name="l00430"></a>00430     }
<a name="l00431"></a>00431 }
<a name="l00432"></a>00432 
<a name="l00433"></a>00433 } <span class="comment">// namespace sf</span>
</pre></div></div>

        <p id="footer">
            &nbsp;::&nbsp; Copyright &copy; 2007-2008 Laurent Gomila, all rights reserved &nbsp;::&nbsp;
            Documentation generated by <a href="http://www.doxygen.org/" title="doxygen website">doxygen 1.5.2</a> &nbsp;::&nbsp;
        </p>

    </body>
</html>