Lecture 24

advertisement
Lecture 24
●
●
●
●
●
Log into Linux.
Copy directory /home/hwang/cs375/lecture24
Final project posted. Due during finals week.
Reminder: No class next Tuesday (11/24)
Questions?
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
1
Outline
●
Internet (IP) sockets
●
Concurrent servers
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
2
Internet (IP) Sockets
●
●
●
IP or Internet sockets can be used to
communicate between two processes on two
different machines connected by a network. (Or
for IPC on a single machine.)
An IP socket is an address/port-number pair
and uniquely identifies an endpoint.
A IP socket pair consists of both the server and
client sockets. Every TCP connection is
uniquely associated with a socket pair.
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
3
Internet (IP) Sockets
Client
198.69.10.2
Server
206.62.226.35
Client
102.43.83.204
client1
server
client1
198.69.10.2:1500
206.62.226.35:21
(*:21, *.*)
102.43.83.204:1501
206.62.226.35:21
client2
198.69.10.2:1501
206.62.226.35:21
Thursday, November 19
server
(child1)
server
(child2)
206.62.226.35:21
198.69.10.2:1500
206.62.226.35:21
102.43.83.204:1501
server
(child3)
206.62.226.35:21
198.69.10.2:1501
CS 375 UNIX System Programming - Lecture 24
4
Internet (IP) Sockets
●
●
Just as for local sockets, the server will call
socket( ), bind( ), listen( ), and accept( ).
First call socket( ) to create the socket:
sfd = socket(domain, type, protocol);
●
The domain parameter is now PF_INET. type
is usually either SOCK_DGRAM (UDP) or
SOCK_STREAM (TCP). (We will use
SOCK_STREAM.) The protocol should be 0.
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
5
Internet (IP) Sockets
●
bind( ) is used to assign an address (TCP port)
to the socket. Address family is now AF_INET.
struct sockaddr_in in_addr; // network
struct sockaddr *p_addr =
(struct sockaddr *)(&in_addr);
in_addr.sin_family = AF_INET;
in_addr.sin_port = htons(2400);
in_addr.sin_addr.s_addr =
htonl(INADDR_ANY);
int len = sizeof(struct sockaddr_in);
bind(sfd, p_addr, len);
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
6
Internet (IP) Sockets
●
●
●
On the server, we bind our socket to a particular
IP address and port number.
An IP address of INADDR_ANY will bind to all
local IP addresses. We could instead bind to a
single IP address on a single interface.
Our server will bind to port 2400 in this
example. Note the use of the htonl( ) and
htons( ) routines.
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
7
Internet (IP) Sockets
●
Instead of binding to a particular port, if we
specify a port number of 0 in the address we
will be assigned an available port number
dynamically. The getsockname( ) routine can
then be used to find the port number:
getsockname(sfd, p_addr, &addrlen);
cout << “Port #: ” << ntohs(in_addr.sin_port)
<< endl;
●
Note the use of ntohs( ).
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
8
Internet (IP) Sockets
●
The server then uses listen( ) and accept( )
just as for UNIX sockets.
result = listen(sfd, qlength);
nfd = accept(sfd, p_addr, &len);
●
The p_addr parameter is a pointer to a
sockaddr structure (that is really of type
sockaddr_in). This will be filled with connecting
client info (IP address and port number).
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
9
Internet (IP) Sockets
●
On the client we need only socket( ) and
connect( ). We use the server IP and port
numbers in the address:
cfd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in in_address;
struct sockaddr *address =
(struct sockaddr *)(&in_address);
in_address.sun_family = AF_INET;
in_address.sin_port = htons(2400);
in_address.sin_addr.s_addr = inet_addr("10.10.0.9"); // csserver
int len = sizeof(struct sockaddr_in);
res = connect(cfd, address, len);
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
10
Internet (IP) Sockets
●
●
In this example inet_addr( ) was used to
convert an IP number from dotted-quad to
network byte order. Typically the IP number
would be obtained via getaddrinfo( ).
Since our socket file descriptor is not bound to a
local endpoint, connect( ) will do this for us.
This is usually what we want. You could use
bind( ) to bind to a particular local port number
before the call to connect( ).
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
11
Internet (IP) Sockets
●
●
read( ) and write( ) can be used to send data
via the socket.
There also are recv( ) and send( ) routines that
can used and often are recommended because
they provide more options via their flags
parameter. Consult the man pages, if you want
to use these.
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
12
Examples
●
●
network_server.cpp is an example server. It is
similar to the local_server.cpp from last lecture
but is modified to use a TCP/IP socket instead
of a local (UNIX) socket. It illustrates dynamic
port assignment and the use of
getsockname( ).
network_client.cpp is a similarly modified
version of local_client.cpp. It requires two
command-line arguments, an IP address (in
dotted-quad notation) and a port number.
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
13
Concurrent Server
●
Skeleton code for a concurrent server ...
listenfd = socket( ... );
bind( listenfd, ... );
listen(listenfd, ... );
while ( true ) {
connfd = accept( listenfd, ... );
if( (pid = fork()) == 0) {
close( listenfd ); doit(connfd);
// or exec(...)
close( connfd ); // if not exec'd
exit(0);
}
close( connfd ); // parent
}
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
14
Concurrent Server
●
It is important that the parent call close( ) for
each connected socket returned by accept( ).
This ensures that the parent does not run out of
file descriptors, but more importantly it ensures
that when the child closes the connected socket
the client connection will be terminated. (This
does not happen until the open reference count
on the socket reaches zero.)
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
15
Avoiding Zombies
●
●
As noted previously, the parent of an exiting
process must issue a wait on the process for it
to terminate completely.
We do not want the main server process to
have to issue these waits for the processes
handling client requests. Typically, in order to
avoid creating zombie processes, the doublefork technique covered earlier is used.
Thursday, November 19
CS 375 UNIX System Programming - Lecture 24
16
Download