Berkeley Sockets

advertisement
CS 360
Intro to Socket Programming
Two views: Server vs. Client
 Servers LISTEN for a connection and respond when one is made
Usually, server processes are not programmed to exit and are frequently called
“daemons”.
 They “listen” for an incoming connection on a particular PORT number.
 Ports 0 through 1023 are preassigned and require root privileges to listen to.
 Ports >1023 are termed ephemeral (mostly not preassigned).
 Usually, when a connection is made to a server, it forks off a child process
which responds to the client while the parent listens for another connection.
 Clients actively make a connection to a server
 An Internet address (xxx.xxx.xxx.xxx) and a port number are selected by the
client.
 It then attempts to connect to that host/port number
 If the connection succeeds, it proceeds to read and write data through its
connection.
 For our purposes, we will only use TCP (no UDP)
 Reliable, connection-oriented protocol

Page 2
CS 360, WSU Vancouver
Server side programming
 Synopsis:



Make a socket using socket()
Bind the socket to a port number using bind() to give it an “address” on the
net
Call listen() to establish our process as a server.
– However, listen() does not actually listen





Page 3
Wait for a completed connection to be established with accept()
When a connection is accepted, use fork() to create a child process
The parent closes child’s socket and loops back to accept another connection
The child process services the client connection and eventually exits.
At some point the parent should use waitpid() to prevent “zombie”
processes
CS 360, WSU Vancouver
Important header files
 Generally, you will need to include the following header files:





sys/types.h
sys/socket.h
netinet/in.h
arpa/inet.h
netdb.h
 An important type that holds the data associated with an Internet address:
struct sockaddr_in { }
length
AF_INET
16 bit port number
32 bit
IP version 4 address
Unused
Page 4
CS 360, WSU Vancouver
Make a socket
int listenfd;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
• AF_INET is the domain -> Internet
•SOCK_STREAM is the protocol family (TCP)
•If the result is < 0, there is an error, use perror() to print the
message
Page 5
CS 360, WSU Vancouver
Bind the socket to a port
#define MY_PORT_NUMBER 49999
struct sockaddr_in servAddr;
memset(&servAddr, 0, sizeof(servAdder));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(MY_PORT_NUMBER);
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if ( bind( listenfd,
(struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) {
perror(“bind”);
exit(1);
}
Page 6
CS 360, WSU Vancouver
Listen and Accept connections
listen( listenfd, 1)
• Sets up a connection queue one level deep
int connectfd;
int length = sizeof(struct sockaddr_in);
struct sockaddr_in clientAddr;
connectfd = accept(listenfd,
(struct sockaddr *) &clientAddr,
&length);
• Waits (blocks) until a connection is established by a client
• When that happens, a new descriptor for the connection is returned
• If there is an error the result is < 0;
• The client’s address is written into the sockaddr structure
Page 7
CS 360, WSU Vancouver
Getting a text host name
struct hostent* hostEntry;
char* hostName;
hostEntry = gethostbyaddr(&(clientAddr.sin_addr),
sizeof(struct in_addr), AF_INET);
hostName = hostEntry->h_name;
 Uses DNS to convert a numerical Internet address to a host name
 Returns NULL if there is an error, use herror() to print the error message, it
has the same argument as perror()
Page 8
CS 360, WSU Vancouver
Making a connection from a client
int socketfd;
socketfd = socket( AF_INET, SOCK_STREAM, 0);
 Make an Internet socket using TCP protocol
 Same as server code
Page 9
CS 360, WSU Vancouver
Set up the address of the server
struct sockaddr_in servaddr;
struct hostent* hostEntry;
struct in_addr **pptr;
memset( &servAddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(MY_PORT_NUMBER);
hostEntry = gethostbyname(“lx.encs.vancouver.wsu.edu”);
/* test for error using herror() */
/* this is magic, unless you want to dig into the man pages
*/
pptr = (struct in_addr **) hostEntry->h_addr_list;
memcpy(&servAddr.sin_addr, *pptr, sizeof(struct in_addr));
 Plug in the family and port number
 Get the numeric form of the server address
 Copy it into the address structure
Page 10
CS 360, WSU Vancouver
Connect to the server
connect(socketfd, (struct sockaddr *) &servAddr,
sizeof(servAddr));
 A connection is established, after which I/O may be performed on socketfd

This is the file I/O equivalent of “open()”
 Or, there is an error which is indicated by the return being < 0

Page 11
Always check for an error…
CS 360, WSU Vancouver
Socket I/O
 Use Unix read() and write() using the descriptor for the connected socket in
the same manner as file I/O.
 EXCEPT:





Read operations on a socket may return less than the requested number of
bytes (in the manner of reading from a pipe).
This is NOT an indication of the last block of data.
Continue reading until the number of bytes read is zero (implying EOF).
Just like I/O with pipes except socket descriptors are bi-directional
Always test for errors on reads or writes
 Use use the Unix netstat utility in the shell to observe open ports, established
connections, etc.
Page 12
CS 360, WSU Vancouver
Lab Assignment
 Write two programs
daytime.c
 dayserve.c
dayserve is a server process that listens on an ephemeral TCP port for one connection.
 When it receives a connection, it logs the hostname of the client to stdout and writes the
current date and time to the client via the socket connection.
 See library routines time() and ctime() to obtain and format the time of day
 Suggestion: start by writing some string of your own choosing to the client
daytime is a client program that takes one argument on the command line. That
argument is the server’s host name or IP address (in dotted decimal). It makes a TCP
connection to the indicated host and dayserve’s port number (or indicates the error, if it
cannot) and then writes the information received from dayserve to stdout.
Use port number 49999 (that way you can communicate with each other ’s servers)
Demonstrate your client and server programs in lab by the end of lab on Friday, April
17th. Submit the following files by email by the end of the day:
 daytime.c
 dayserve.c
You will need this code and these capabilities for the final project so you would be wise
to modularize/encapsulate them for subsequent re-use.






Page 13
CS 360, WSU Vancouver
Download