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
|
/*
* The Unix Channel
*
* by Michel Beaudouin-Lafon
*
* Copyright 1990-1993
* Laboratoire de Recherche en Informatique (LRI)
*
* Streams
*
* $Id$
* $CurLog$
*/
#include "Stream.h"
#include <stdlib.h>
#include <sys/socket.h>
/*?class UchStream
Streams implement reliable point to point connections.
UchStream connections do not keep the message boundaries:
several messages can be read at a time, and a message can be read in several parts.
Establishing a stream connection is not a symmetric operation:
one process (the server) creates a bound socket and listens to it (with function \fun{Listen});
other processes (the clients) create sockets and connect them to the address of the server.
Each such connection is accepted (\fun{SockAccept}) by the server and results in the creation of a new socket.
Communication with each client will then proceed on this channel,
while the server still can accept connections.
Because a server has to listen to pending connections and communicate
with its connected clients, using a channel set is highly recommended:
when a connection is pending, the channel is ready for reading,
and you can accept the connection with \fun{SockAccept} (instead of reading data).
Note that because \typ{UchStream} derives from \typ{UchSocket}
and thus from \typ{UchChannel}, the virtual functions
\fun{HandleRead} and \fun{HandeWrite} can be used.
?*/
/*?nextdoc?*/
UchStream :: UchStream ()
: UchSocket ()
{
}
/*?
These constructors are similar to those of the class \typ{UchSocket}.
?*/
UchStream :: UchStream (UchAddress* bound, UchAddress* connected)
: UchSocket (bound, connected)
{
}
/*?nodoc?*/
UchStream :: UchStream (const UchStream& s)
: UchSocket (s)
{
}
/*?nodoc?*/
UchStream :: ~UchStream ()
{
}
/*?nodoc?*/
UchChannel*
UchStream :: Copy () const
{
return new UchStream (*this);
}
/*?nodoc?*/
int
UchStream :: SockType ()
{
return SOCK_STREAM;
}
/*?
This function implements the Unix system call \fun{listen}.
\var{n} is the maximum number of pending connections:
if \var{n} clients are waiting for the server to accept their connection,
the next client will have its connection refused.
You can safely use the default value.
The stream socket is first set up (with \fun{Setup}), and then the system call is performed.
The returned value is that of the system call, unless the set up failed in which case
-1 is returned.
Note that it is useless to listen on a socket if it is not bound to an address.
?*/
int
UchStream :: Listen (int n)
{
if (! Setup ())
return -1;
return listen (FilDes (), n);
}
/*?
This function implements the Unix system call \fun{accept}.
The stream socket is first set up (with \fun{Setup}), and then the system call is performed.
A new dynamically created socket is returned, connected to the address returned by \fun{accept}.
If the socket could not be set up or a system error occurred, 0 is returned.
Note that in order to accept connections, the socket must be listen to,
and thus an address must be bound to it.
?*/
UchSocket*
UchStream :: SockAccept ()
{
GEN_ADDR addr;
int alen = sizeof (addr);
int fd;
if (! Setup ())
return (UchSocket*) 0;
if ((fd = accept (FilDes (), &addr.sa, &alen)) < 0)
return (UchSocket*) 0;
UchSocket* s = new UchSocket (0, UchAddress::Decode (&addr, alen));
s -> UchChannel :: Open (fd);
return s;
}
|