1 / 58

TDC561 Network Programming

TDC561 Network Programming. Week 5: Client/Server Programming Aspects Client side: Identifying the Server; Specifying a local IP address; TCP client design, UDP client design. Server Side: Daemon, inetd.

mburks
Download Presentation

TDC561 Network Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. TDC561 Network Programming Week 5: Client/Server Programming Aspects • Client side: Identifying the Server; Specifying a local IP address; TCP client design, UDP client design. • Server Side: Daemon, inetd. Socket Options ( discussion will continue in a next lecture ) Camelia Zlatea, PhD Email: czlatea@cs.depaul.edu

  2. Douglas Comer, David Stevens, Internetworking with TCP/IP : Client-Server Programming, Volume III (BSD Unix and ANSI C), 2nd edition, 1996 (ISBN 0-13-260969-X) Chap. 6, 14 (partial) W. Richard Stevens, Network Programming : Networking API: Sockets and XTI, Volume 1, 2nd edition, 1998 (ISBN 0-13-490012-X) Chap. 7,11,12, 21,22 References

  3. Aspects of Client/Server Programming • Client-side aspects: • Identifying the Server. • Looking up an IP address. • Looking up a well known port name. • Specifying a local IP address. • TCP client design. • UDP client design. • Server-side aspects: • daemons • inetd

  4. Identifying the Server • Need an IP address, protocol and port. • often use host names instead of IP addresses. • usually the protocol (UDP vs. TCP) is not specified by the user. • often the port is not specified by the user. • Options: • hard-coded into the client program. • require that the user identify the server. • read from a configuration file. • use a separate network service to lookup the identity of the server.

  5. Services and Ports • Identifying of the server • Many services are available via “well known” addresses (names). • There is a mapping of service names to port numbers: • struct *servent getservbyname( char *service, char *protocol ); • servent->s_port is the port number in network byte order. • Specifying a Local Address • When a client creates and binds a socket it must specify a local port and an IP address. • A client ask the kernel to assign the local IP address: haddr->sin_addr.s_addr= htonl(INADDR_ANY); • Typically a randomly port available is assigned with: haddr->port = htons(0);

  6. Example: Identifying the Server • Option: read from a configuration file. /* Initialize the server structure */ server.sin_addr.s_addr = INADDR_ANY; server.sin_family = AF_INET; /* Get the service port associated with this process usually in some /etc/ config file such as /etc/services */ servent_p = getservbyname ( PMSERVICE, “tcp” ); server.sin_port = servent_p->s_port;

  7. DNS library functions: gethostbyname #include <netdb.h> struct hostent *gethostbyname( const char *hostname); struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; };

  8. hostent Official Name h_name h_aliases h_addrtype h_length h_addr_list alias 1 alias 2 null h_addr_list[0] (IP address 1) h_addr_list[1] (IP address 2) null All the IP addresses returned via the hostent are in network byte order #define h_addr h_addr_list[0]

  9. DNS library functions: gethostbyname • On error gethostbyname return null. • gethostbyname sets the global variable h_errno to indicate the exact error: • HOST_NOT_FOUND • TRY_AGAIN • NO_RECOVERY • NO_DATA • NO_ADDRESS

  10. Getting host IP address: char **h_addr_list; h = gethostbyname(“hawk.depaul.edu"); memcpy(&sockaddr.sin_addr, h->h_addr_list[0], sizeof(struct in_addr));

  11. DNS library functions: gethostbyaddr struct hostent *gethostbyaddr( const char *addr size_t len, int family);

  12. Other DNS library functions • Shell Command uname –n • get hostname of local host • uname –aprints all info local host • getservbyname • get port number for a named service • getservbyaddr • get name for service associated with a port number

  13. Name/Address Conversion • Protocol dependent DNS library functions • gethostbyname • gethostbyaddr • Posix protocol independent functions • getaddrinfo() • getnameinfo() • getaddrinfo()and getnameinfo() functions provide name/address conversions as part of the sockets library. • designed to support writing code that can run on many protocols (IPv4, IPv6)

  14. POSIX: getaddrinfo() int getaddrinfo( const char *hostname, const char *service, const struct addrinfo* hints, struct addrinfo **result); • hostname is a hostname or an address string (dotted decimal string for IP). • service is a service name or a decimal port number string. • getaddrinfo() • provides the combined functionality of gethostbyname()andgetservbyname()

  15. POSIX: getaddrinfo() • result is returned with the address of a pointer to an addrinfo structure that is the head of a linked list. struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; char *canonname; struct sockaddr *ai_addr; struct addrinfo *ai_next; }; used by socket() used by: bind() connect() sendto()

  16. POSIX: getnameinfo() int getnameinfo( const struct sockaddr *sockaddr, socklen_t addrlen char *host, size_t hostlen, char *serv, size_t servlen, int flags); getnameinfo() looks up a hostname and a service name given a sockaddr

  17. TCP Client Design • Identify and establish server address (IP and port). • Allocate a socket. • Request OS to use any valid local port and IP address • Call connect() • Communicate with server (read,write). • Close the connection.

  18. Stream Socket Transaction (TCP Connection) Server socket() Client bind() socket() listen() 3-way handshake connect() accept() write() data read() data write() read() EOF close() read() close()

  19. Closing a TCP socket • Many TCP based application protocols support multiple requests and/or variable length requests over a single TCP connection. • How does the server known when the client is done ? • When it is safe to close the socket?

  20. Partial Close • One solution is for the client to shut down only it’s writing end of the socket. • The shutdown() system call provides this function. shutdown( int s, int direction); • direction can be 0 to close the reading end or 1 to close the writing end. • shutdown sends info to the other process

  21. TCP Sockets Programming • Typical issues : • reads don’t correspond to writes. • synchronization (including close()) • TCP Reads: • Each call to read() on a TCP socket returns any available data (up to a maximum). • TCP buffers data at both ends of the connection.

  22. UDP Client Design • Identify and establish the server address (IP and port). • Allocate a socket. • Request OS to use any valid local port and IP address • Communicate with server (send, recv) • Close the socket.

  23. Datagram Socket Transaction (UDP Connection) Server Client socket() socket() bind() sendto() data recvfrom() data sendto() recvfrom() close()

  24. Datagram Sockets • Connectionless sockets, i.e., C/S addresses are passed along with each message sent from one process to another • Peer-to-Peer Communication • Provides an interface to the UDP datagram services • Handles network transmission as independent packets • Provides no guarantees, although it does include a checksum • Does not detect duplicates • Does not determine sequence • ie information can be lost, wrong order or duplicated

  25. Daemons • Most servers run as a daemon process • Typical UNIX daemons: • Web server (httpd) • Mail server (sendmail) • SuperServer (inetd) • System logging (syslogd) • Print server (lpd) • router process (routed, gated)

  26. Daemon Process • A daemon is a process that: • runs in the background • not associated with any terminal • output doesn't end up in another session. • ignore SIGINT (such as terminal generated signals - ^C • since is not associated with any terminal uses • file system • central logging facility • daemons should close all unnecessary descriptors • often including stdin, stdout, stderr. • daemons often change working directory. • A background process • Parent process fork() and then the parent exit(). • A way to disassociate a process from a terminal. • Call setsid() and then fork() again.

  27. Daemon Process Init – Example #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int daemon_init(void) { pid_t pid; if ( (pid = fork()) < 0) return(-1); else if (pid != 0) exit(0); /* parent is gone */ /* child continues */ setsid(); /* become session leader */ system(“cd /"); /* change working directory */ umask(0); /* clear our file mode creation mask */ close(0); close(1); close(2); /* stdin, stdout, stderr */ return(0); }

  28. Performance issues with daemons processes • CPU utilization • There can be many servers running as daemons -and idle most of the time. • Memory utilization • Most daemons/servers are suspended most of the time, but still occupy space in the process table. • A solution: Superserver or inetd (Internet services daemon )

  29. inetd • the SuperServer is named inetd. • inetd daemon creates multiple sockets and waits for (multiple) incoming requests. • inetd typically uses select to watch multiple sockets for input. • when a request arrives, inetd will fork and the child process handles the client. • inetd child process closes all unnecessary sockets. • inetd child dup’s the client socket to descriptors 0,1 and 2 (stdin, stdout, stderr). • inetd child exec’s the real server program, which handles the request and exits.

  30. inetd based servers • Servers that are started by inetd assume that the socket holding the request is already established (descriptors 0,1 or 2). • TCP servers started by inetd don’t call accept, so they must call getpeername if they need to know the address of the client. • inetd reads a configuration file that lists all the services it should handle. • /etc/inetd.conf • inetd creates a socket for each listed service, and adds the socket to a fd_set given to select().

  31. getpeername #include <sys/types.h> #include <sys/socket.h> int getpeername(int s, struct sockaddr *name, socklen_t *namelen); • getpeername() returns the name of the peer connected to socket s.

  32. inetd service specification • For each service, inetd needs to know: • the socket type and transport protocol • wait/nowait flag. • login name the process should run as. • pathname of real server program. • command line arguments to server program. • Servers that are expected to deal with frequent requests are typically not run from inetd • mail, web, NFS.

  33. Example /etc/inetd.conf # Syntax for socket-based Internet services: # <service_name> <socket_type> <proto> <flags> <user> <server_pathname> <args> # # comments start with # echo stream tcp nowait root internal echo dgram udp wait root internal chargen stream tcp nowait root internal chargen dgram udp wait root internal ftp stream tcp nowait root /usr/sbin/ftpd ftpd -l telnet stream tcp nowait root /usr/sbin/telnetd telnetd finger stream tcp nowait root /usr/sbin/fingerd fingerd # Authentication auth stream tcp nowait nobody /usr/sbin/in.identd in.identd -l -e -o # TFTP tftp dgram udp wait root /usr/sbin/tftpd tftpd -s /tftpboot

  34. wait/nowait • WAIT specifies that inetd should not look for new clients for the service until the child (the real server) has terminated. • TCP servers usually specify nowait - this means inetd can start multiple copies of the TCP server program - providing concurrency • Most UDP services run with inetd told to wait until the child server has died.

  35. Topic Socket Options(discussion will continue in a next lecture)

  36. Socket Options • Various attributes that are used to determine the behavior of sockets. • Setting options tells the OS/Protocol Stack the behavior we want. • Support for generic options (apply to all sockets) and protocol specific options.

  37. Option types • Many socket options are Boolean flags indicating whether some feature is enabled (1) or disabled (0). • Other options are associated with more complex types including int, timeval, in_addr, sockaddr, etc.

  38. Read-Only Socket Options • Some options are readable only (we can’t set the value).

  39. Setting and Getting option values #include <sys/socket.h> getsockopt() gets the current value of a socket option. setsockopt() is used to set the value of a socket option.

  40. getsockopt() int getsockopt( int sockfd, int level, int optname, void *opval, socklen_t *optlen); level specifies whether the option is a general option or a protocol specific option (what level of code should interpret the option).

  41. setsockopt() int setsockopt( int sockfd, int level, int optname, const void *opval, socklen_t optlen);

  42. General Options • Protocol independent options. • Handled by the generic socket system code. • Some general options are supported only by specific types of sockets (SOCK_DGRAM, SOCK_STREAM).

  43. Some Generic Options SO_BROADCAST SO_DONTROUTE SO_ERROR SO_KEEPALIVE SO_LINGER SO_RCVBUF,SO_SNDBUF SO_REUSEADDR

  44. SO_BROADCAST • Boolean option: enables/disables sending of broadcast messages. • Underlying data layer must support broadcasting • Applies only to SOCK_DGRAM sockets. • Prevents applications from inadvertently sending broadcasts (OS looks for this flag when broadcast address is specified).

  45. SO_DONTROUTE • Boolean option: enables bypassing of normal routing. • Used by routing daemons.

  46. SO_ERROR • Integer value option. • The value is an error indicator value (similar to errno). • Readable only • Reading (by calling getsockopt()) clears any pending error.

  47. SO_KEEPALIVE • Boolean option: enabled means that STREAM sockets should send a probe to peer if no data flow for a “long time”. • Used by TCP - allows a process to determine whether peer process/host has crashed. • Consider what would happen to an open telnet connection without keepalive.

  48. SO_LINGER Value is of type: struct linger { int l_onoff; /* 0 = off */ int l_linger; /* time in seconds */ }; • Used to control whether and how long a call to close will wait for pending ACKS. • connection-oriented sockets only.

  49. SO_LINGER usage • By default, calling close() on a TCP socket will return immediately. • The closing process has no way of knowing whether or not the peer received all data. • Setting SO_LINGER means the closing process can determine that the peer machine has received the data (but not that the data has been read() !).

  50. shutdown() vs SO_LINGER • How you can use shutdown() to find out when the peer process has read all the sent data [see R.Stevens, 7.5]

More Related