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
|
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>
<TITLE>nevrax.org : docs</TITLE>
<LINK REL=stylesheet TYPE="text/css" HREF="/inc/css/nevrax.css">
<link href="doxygen.css" rel="stylesheet" type="text/css">
</HEAD>
<BODY MARGINHEIGHT="0" MARGINWIDTH="0">
<!-- uplinks -->
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0>
<TR>
<TD WIDTH=16><IMG SRC="/inc/img/pixel.gif" WIDTH="16" HEIGHT="16" BORDER=0 ALT=""></TD>
<TD WIDTH=140 BGCOLOR=#dddddd><IMG SRC="/inc/img/pixel.gif" WIDTH="140" HEIGHT="16" BORDER=0 ALT=""></TD>
<TD WIDTH=16><IMG SRC="/inc/img/pixel.gif" WIDTH="16" HEIGHT="16" BORDER=0 ALT=""></TD>
<TD><IMG width=6 height=14 SRC="/inc/img/reddots.gif" ALT="#" VSPACE=2 HSPACE=2 BORDER=0 ></TD><TD VALIGN=middle> <A CLASS=uplinks HREF='/'><b>Home</B></FONT></A> </TD>
<TD><IMG width=6 height=14 SRC="/inc/img/reddots.gif" ALT="#" VSPACE=2 HSPACE=2 BORDER=0 ></TD><TD VALIGN=middle> <A CLASS=uplinks HREF=><b>nevrax.com</B></FONT></A> </TD>
</TR>
</TABLE>
<!-- banner Nevrax -->
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 WIDTH=100%>
<TR><TD BGCOLOR="#000000" BACKGROUND="/inc/img/black_banner.jpg"><A HREF=""><IMG SRC="/inc/img/nevrax.gif" WIDTH="170" HEIGHT="45" BORDER=0 ALT="Nevrax" ></A></TD></TR>
</TABLE>
<!-- main table -->
<TABLE CELLSPACING=0 CELLPADDING=0 BORDER=0 height=100%>
<TR>
<TD WIDTH=16><IMG SRC="/inc/img/pixel.gif" WIDTH="16" HEIGHT="10" BORDER=0 ALT=""></TD>
<TD WIDTH=140 BGCOLOR=#dddddd VALIGN=TOP ALIGN=middle><IMG SRC="/inc/img/pixel.gif" WIDTH="140" HEIGHT="10" BORDER=0 ALT="">
<!------ Begin Box ------>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 BGCOLOR=black><TR><TD><TABLE border=0 cellspacing=2 cellpadding=0 width=120><tr><TD ALIGN=middle bgcolor=black>
<FONT COLOR=white FACE="sans-serif"><B>Nevrax.org</B></FONT></TD></TR><tr><td colspan=2 bgcolor=#FFFFFF>
<TABLE cellspacing=0 cellpadding=1 border=0>
<tr><td ALIGN=middle><a class='linkbox' href="/news/" TITLE="Rubrique news"><img width=13 height=15 hspace=5 border=0 src=/inc/img/picto-news.gif ALT=#></A></td><td><a class='linkbox' href="/news/" TITLE="News">News</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/mail/" TITLE="Rubrique mail"><img width=15 height=11 hspace=5 border=0 src=/inc/img/picto-mail.gif ALT=#></A></td><td><a class='linkbox' href="/mail/" TITLE="Mailing list archive">Mailing-list</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/docs/" TITLE="Rubrique docs"><img width=14 height=16 hspace=5 border=0 src=/inc/img/picto-docs.gif ALT=#></A></td><td><a class='linkbox' href="/docs/" TITLE="Documentation">Documentation</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/cvs/" TITLE="Rubrique cvs"><img width=13 height=17 hspace=5 border=0 src=/inc/img/picto-cvs.gif ALT=#></A></td><td><a class='linkbox' href="/cvs/" TITLE="CVS Web">CVS</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/bugs/" TITLE="Rubrique bugs"><img width=20 height=16 hspace=5 border=0 src=/inc/img/picto-bugs.gif ALT=#></A></td><td><a class='linkbox' href="/bugs/" TITLE="Bugtracking">Bugs</a></td></tr>
<tr><td ALIGN=middle><a class='linkbox' href="/GPL.php3" TITLE="Rubrique license"><img width=18 height=12 hspace=5 border=0 src=/inc/img/picto-gpl.gif ALT=#></A></td><td><a class='linkbox' href="/GPL.php3" TITLE="License">License</a></td></tr>
</TABLE>
</TD></TR></TABLE></TD></TR></TABLE>
<!------ End Box ------>
</TD>
<TD WIDTH=15><IMG SRC="/inc/img/pixel.gif" WIDTH="16" HEIGHT="16" BORDER=0 ALT=""></TD>
<TD ALIGN=left valign=top><IMG SRC="/inc/img/pixel.gif" WIDTH="140" HEIGHT="10" BORDER=0 ALT="">
<!-- title -->
<TABLE background="/inc/img/redline.gif" CELLSPACING=0 CELLPADDING=0 BORDER=0 width=100%><tr><td>
<A HREF="/docs/"><img src="/inc/img/t_docs.gif" ALT="Docs" HEIGHT=20 BORDER=0></A>
</td><td><IMG SRC="/inc/img/pixel.gif" WIDTH="1" HEIGHT="1" BORDER=0 ALT="">
</td></tr></table>
<!-- block -->
<TABLE bgcolor="#dddddd" CELLSPACING=0 CELLPADDING=0 BORDER=0 width=100%><tr><td width=1% valign=middle><img width=6 height=14 hspace=2 vspace=2 src="/inc/img/reddots.gif"></TD>
<TD><B>Documentation</B></TD>
<TD ALIGN=RIGHT> </td>
</tr></table>
<!-- Generated by Doxygen 1.2.14 -->
<center>
<a class="qindex" href="index.html">Main Page</a> <a class="qindex" href="namespaces.html">Namespace List</a> <a class="qindex" href="hierarchy.html">Class Hierarchy</a> <a class="qindex" href="classes.html">Alphabetical List</a> <a class="qindex" href="annotated.html">Compound List</a> <a class="qindex" href="files.html">File List</a> <a class="qindex" href="namespacemembers.html">Namespace Members</a> <a class="qindex" href="functions.html">Compound Members</a> <a class="qindex" href="globals.html">File Members</a> <a class="qindex" href="pages.html">Related Pages</a> <a class="qindexRef" doxygen="_cgi:/cgi-bin/nel-search.cgi" href="/cgi-bin/nel-search.cgi">Search</a> </center>
<hr><a name="netlayer1"><h2>NeL Net Layer 1</h2></a>
<dl compact><dt><b>
Author: </b><dd>
Olivier Cado</dl><dl compact><dt><b>
Date: </b><dd>
May 10, 2001</dl><a name="l1server"><h2>Server</h2></a>
<p>
<a name="l1serverstruct"><h3>Server structure</h3></a>
<p>
The server provides a single receive queue (see "Receive FIFO Buffer" on the object diagram below), and one send queue per connection ("Send FIFO Buffer"). Internally, each connection is associated with a receive buffer to handle non-blocking receiving of uncomplete data blocks (in CServerBufSock). The actual receives and sends are done by CTcpSock (from layer 0).
<p>
<div align="center">
<img src="nelnet-layer1-server-obj.png" alt="nelnet-layer1-server-obj.png">
</div>
Every connection is managed by a receive thread (CServerReceiveTask). Instead of having one thread per connection (it would slow the system down and the system limitations would limit the maximum number of connections), there is a pool of threads that handle several connections. For example, 30 threads handling 30 connections allow 900 simultaneous connections. If only one thread was in charge of all the connections, the select() operation would take too much overhead for a large number of sockets.
<p>
<a name="l1servlaunch"><h3>Launching the server</h3></a>
<p>
The server (CBufServer) starts a listening socket (CListenSock), handled by a particular thread (CListenTask). It can then accept incoming connections.
<p>
<a name="l1servaccept"><h3>Accepting a connection</h3></a>
<p>
When a connection is accepted, the server advertises the connection by pushing a connection event into the receive queue, and it dispatches the associated socket to a receive thread from the pool (or a new one).
<p>
<a name="l1servread"><h3>Reading data</h3></a>
<p>
The user of layer 1 (note: it can be a higher NeL Net level) calls CBufServer::dataAvailable() to check for incoming data. If a connection or disconnection event is found at the top of the receive queue, the associated system callback is called. Then the socket is logically connected (CBufSock::connectedState() is true) in case of a connection event.
<p>
If dataAvailable() returned true, the user calls CBufServer::receive(data,&sockid). The second argument tells from which connection the data is coming. It can reply to it directly, by calling CBufServer::send(replydata,sockid).
<p>
The user must call CBufServer::update() for the system to work properly.
<p>
<a name="l1servsend"><h3>Sending data</h3></a>
<p>
The sending is buffered as well. The moment when the data is actually sent depends on the triggers specified. By default, the time trigger is enabled, with a value of 20 ms. It means the data will be actually sent after 20 milliseconds, provided update() is called evenly. The user can also specify a size trigger: when the size in the send buffer exceeds the specified size, the data is sent. Eventually, the user can force sending by calling flush().
<p>
<a name="l1servnbrecv"><h3>How the non-blocking receiving works</h3></a>
<p>
Each receiving thread (CServerReceiveTask) performs a select() on its sockets. When incoming data is reported, the method CServerBufSock::receivePart() tries to read a block (which is made up of a length prefix and a payload buffer). If the actually received data is smaller than expected, it is retained in the receive buffer, for later completion. When it is complete, it is pushed into the main receive queue.
<p>
<a name="l1servnbsend"><h3>How the non-blocking sending works</h3></a>
<p>
All data from a send queue is copied into a buffer, then sent actually. If the sending was not done in its entirety (or it would block), part the buffer is kept for later sending.
<p>
<a name="l1servdisc"><h3>Handling a disconnection</h3></a>
<p>
When a receive thread detects that a socket is disconnected, a disconnection event is pushed into the receive queue by the next CBufServer::update(). When the disconnection event is processed (at the top of the receive queue), the socket is added to the synchronized set of connections to remove of the thread. It will be effectively removed before its next select.
<p>
<a name="l1servwake"><h3>Wake-up pipes (Unix)</h3></a>
<p>
A Unix pipe is added in every select set, so that the select can be stopped when there is a new connection to add to its set or when the server is required to exit. Similarly, the listen thread performs a select on the listen socket and the wake-up pipe.
<p>
Under Windows, the wake-up mechanism is not implemented. Instead, the select timeouts are shorter.
<p>
<a name="l1servsync"><h3>Thread synchronization</h3></a>
<p>
Because of the sharing of data among different threads, some mutexes are used to synchronize data access/modification, on the receive queue, the thread pool, the connections, the set of connections to remove and the connected property of sockets (note: to ensure a fair access to the variables, the GNU/Linux implementation uses a semaphore instead of a pthread_mutex)
<p>
<a name="l1servstats"><h3>Gathering statistics</h3></a>
<p>
Several methods are provided in CBufServer to know how many bytes have been read and written.
<p>
<a name="l1client"><h2>Client (in relation to server)</h2></a>
<p>
The client provides one receive queue and one send queue. The receiving is done is a separate thread (CClientReceiveTask), but the actual sending flush() is done in CBufClient::update(). The socket is in blocking mode.
<p>
Unlike in the server, there is no connection advertisement. A disconnection event is pushed into the receive queue when the receive thread or the sending detects the disconnection. Besides, the client does not remove the socket after disconnecting, but at destruction time, because the user can reuse the same CBufClient object by calling again connect() after having disconnected.
<p>
<!-- footer -->
<BR><FONT Size=+5> </FONT>
</TD>
<TD WIDTH=15><IMG SRC=/inc/img/pixel.gif WIDTH=15 HEIGHT=15 BORDER=0 ALT=""></TD>
</TR>
</TABLE>
</BODY>
</HTML>
|