Presentation is loading. Please wait.

Presentation is loading. Please wait.

Client-Server Communications Servers provide services to clients over a network Most LANs have file servers to manage common disk space This makes it easier.

Similar presentations


Presentation on theme: "Client-Server Communications Servers provide services to clients over a network Most LANs have file servers to manage common disk space This makes it easier."— Presentation transcript:

1 Client-Server Communications Servers provide services to clients over a network Most LANs have file servers to manage common disk space This makes it easier to share files and perform backups Mail and ftp use client-server paradigm

2 Universal Internet Communication Interface (UICI) Simplifies client-server programming UICI is implemented in this chapter with –Sockets –TLI –STREAMS This chapter follows Spec 1170 versions of sockets and TLI since POSIX has not standardized network communications

3 Network Applications ftp – file transfer Kerberos – authentication telnet – remote login NFS – remote filesystems

4 Connectionless Protocol The client sends a single message to the server The server performs a service and sends a reply

5 Connection-Oriented Protocol Server waits for a connection request from a client Once the connection is established, communication takes place using handles (file descriptors) The server address is not included in the user message Connection-oriente protocol has setup overhead This chapter emphasizes connection- oriented protocol

6 Naming of Servers Option 1 – Designate server by process ID and host ID –Process ID is assigned chronolocically at the time process starts running –It is difficult to know process ID in advance on a host Option2 – Name servers with small integers called ports –Server “listens” at a well-known port that has been designated in advance for a particular service –Client explicitly specifies a host address and a port number on the host when setting up a connection

7 Single Port Strategy Simplest client-server communication takes place over a single communication port If client and server are on the same machine, the single port can be a FIFO On a network port can be socket or TLI connection When server starts up, it opens FIFO (or Socket) and waits for client requests When client needs service, it opens FIFO (or Socket) and writes its request Server then performs the service Server Client Requests

8 Single Port Problems There is no mechanism for the server to respond to the client Since items are removed from the port when they are read, there is nothing to prevent one client from taking another’s request

9 Connectionless Protocol Each client has its own channel for receiving responses from the server sendto and receivefrom form the basis of connectionless protocol Server Client Requests Client Server Responses

10 Serial-Server Strategy Two way channel is for additional interaction between client and server Initial client request serves to establish two way communication channel Communication channel is private – not accessable to other processes A busy server handling long-lived requests cannot use serial server strategy ServerClient Client Request Two-Way Communication

11 Serial-Server Pseudocode for (;;) { listen for client request; create private two-way communication channel; while (no error on communication channel) read client request; handle request and respond to client; close communication channel }

12 Parent-Server Strategy Server forks a child to handle actual service Server resumes listing for more requests Similar to switchboard at hotel Server can accept multiple client requests ServerClient Client Request Server Child Two-Way Communication fork

13 Parent-Server Pseudocode for (;;) { listen for client request; create a private two-way communication channel; fork a child to handle the request; close the communication channel; clean up zombies; }

14 Thread-Server Strategy Low overhead alternative to parent-server strategy Create thread to handle request instead of forking child – threads have less overhead Efficient if request is small or I/O intensive Possible interference among multiple requests due to shared address space For computationally intensive services, additional threads may reduce efficiency of or block the main server thread Requires good kernel-level parallelism Server Threads Client Client Request Two-Way Communication

15 UICI Summary UICI PrototypeDescription int u_open(u_port_t port)Opens file descriptor bound to port. Returns listening fd int u_listen(int fd, char *hostn)Listens for connection request on fd. Returns communication fd int u_connect(u_port_t port, char *the_host) Initiates connection to server on port port and host the_host. Returns communication fd int u_close(fd)Closes file descriptor fd ssize_t u_read(int fd, char *buf, size_t nbyte) Reads up to nbyte bytes from fd into buf. Returns number of bytes actually read ssize_t u_write(int fd, char *buf, size_t nbyte) Writes nbyte bytes from buf to fd. Returns number of bytes written void u_error(char *errmsg)Outputs errmsg followed by a UICI error message int u_sync(int fd)Updates relevant kernel info afger calls to exec

16 int copy _from_network_to_file(int communfd, int filefd) { … for ( ; ; ) { if ((bytes_read = u_read(communfd, buf, BLKSIZE)) 0; bufp += bytes_written, bytes_to_write -= bytes_written){ bytes_written = write(filefd, bufp, bytes_to_write); if ((bytes_written) == -1 && (errno != EINTR)){ perror("Server write error"); break; } else if (bytes_written == -1) bytes_written = 0; total_bytes += bytes_written; } if (bytes_written == -1) break; } } return total_bytes; } copy_from_network_to_file

17 void main(int argc, char *argv[]) { u_port_t portnumber; int listenfd; int communfd; char client[MAX_CANON]; int bytes_copied; if (argc != 2) { fprintf(stderr, "Usage: %s port\n", argv[0]); exit(1); } portnumber = (u_port_t) atoi(argv[1]); if ((listenfd = u_open(portnumber)) == -1) { u_error("Unable to establish a port connection"); exit(1); } while ((communfd = u_listen(listenfd, client)) != -1) { fprintf(stderr, "A connection has been made to %s\n",client); bytes_copied = copy_from_network_to_file(communfd, STDOUT_FILENO); fprintf(stderr, "Bytes transferred = %d\n", bytes_copied); u_close(communfd); } exit(0); } Serial Server

18 Parent-Server (top) void main(int argc, char *argv[]) { u_port_t portnumber; int listenfd; int communfd; char client[MAX_CANON]; int bytes_copied; int child; if (argc != 2) { fprintf(stderr, "Usage: %s port\n", argv[0]); exit(1); } portnumber = (u_port_t) atoi(argv[1]); if ((listenfd = u_open(portnumber)) == -1) { u_error("Unable to establish a port connection"); exit(1); }

19 while ((communfd = u_listen(listenfd, client)) != -1) { fprintf(stderr, "[%ld]: A connection has been made to %s\n", (long) getpid(), client); if ((child = fork()) == -1) { fprintf(stderr, "Could not fork a child\n"); break; } if (child == 0) { /* child code */ close(listenfd); fprintf(stderr, "[%ld]: A connection has been made to %s\n", (long) getpid(), client); bytes_copied = copy_from_network_to_file(communfd, STDOUT_FILENO); close(communfd); fprintf(stderr, "[%ld]:Bytes transferred = %d\n", (long) getpid(), bytes_copied); exit(0); } else { /* parent code */ u_close(communfd); while (waitpid(-1, NULL, WNOHANG) > 0) ; } } exit(0); } Parent-Server (bottom)

20 Client (top) void main(int argc, char *argv[]) { u_port_t portnumber; int communfd; ssize_t bytesread; char buf[BLKSIZE]; if (argc != 3) { fprintf(stderr, "Usage: %s host port\n", argv[0]); exit(1); } portnumber = (u_port_t)atoi(argv[2]); if ((communfd = u_connect(portnumber, argv[1])) < 0) { u_error("Unable to establish an Internet connection"); exit(1); }

21 Client (bottom) fprintf(stderr, "A connection has been made to %s\n",argv[1]); for ( ; ; ) { if ((bytesread = read(STDIN_FILENO, buf, BLKSIZE)) < 0) { perror("Client read error"); break; } else if (bytesread == 0) { fprintf(stderr, "Client detected end-of-file on input\n"); break; } else if (bytesread != u_write(communfd, buf, (size_t)bytesread)) { u_error("Client write_error"); break; } } u_close(communfd); exit(0); }

22 UICI Implementation UICISocketsTLIStreams u_opensocket bind listen t_open t_bind create pipe push connld fattach u_listenacceptt_alloc t_listen t_bind t_accept ioctl of I_RECVFD u_connectsocket connect t_open t_bind t_alloc t_connect open u_readreadt_rcvread u_writewritet_sndwrite u_synct_sync

23 u_read an u_write All implementations allow for non-blocking I/O, but UICI interface allows only blocking I/O u_read and u_write cause caller to block u_read blocks until information is available from network connection u_write blocks on a write, on message delivery problems in lower protocol layers, or when all buffers for the network protocols are full u_write returns when output has been transferred – it does not mean the message has been delivered

24 Open Systems Interconnection (OSI) OSI is International Standards Organization (ISO) standard for network design OSI model consists of 7 protocol layers Each layer consists of a set of functions to handle a particular aspect of network communication Functions in a particular layer communicate only with layers directly above and below Low layers are closely related to hardware, high layers are closely related with the user interface

25 Peer-to-Peer OSI Model Application Layer Presentation Layer Session Layer Transport Layer Network Layer Data Link Layer Physical Layer physical path logical connection Network

26 Physical/Data-Link Layers Concerned with point-to-point transmission of data Ethernet is common low-cost implementation of these layers Each host on network has a hardware Ethernet adapter that is connected to a communication link consisting of coaxial cable or twisted pair wire Host is identified by 6-byte Ethernet address that is hard-wired into adapter Other common implementations of this layer are: token ring, token bus, ISDN, ATM, and FDDI

27 Network Layer Handles network addressing and routing through bridges and router interconnecting networks Most common network layer protocol used by UNIX is called IP – Internet Protocol Every host has one or more IP addresses consisting of 4 bytes Common to separate bytes with decimal points (e.g., 198.86.40.81) Users typically refer to machine by name (e.g., sunsite.unc.edu) Convert from name to address with gethostbyname and convert from address to name with gethostbyaddr

28 Transport Layer Handles end-to-end communication between hosts Two main protocols at this layer are Transmission Control Protocol (TCP) and User Datagram Protocol (UDP) UNIX networks use both TCP and UDP UDP is connectionless protocol without guarantee of delivery TCP is reliable connection-oriented protocol

29 Transport Layer Ports More than one user at a time may be using TCP or UDP between a given pair of machines To distinguish between various communicating processes, they use 16 bit integers called ports Well-known addresses –telnet – 23 –tftp – 69 –finger – 79 –User processes – above 7,000 so as not to interfere with system services and X

30 Session Layer Session layer interfaces with the transport layer Two standard interfaces are sockets and Transportation Layer Interface (TLI)

31 Presentation/Application Layers Consists of general utilities and applications Presentation layer may handle compression or encryption

32 OSI Drawbacks Many networks were established before OSI reference model was accepted Therefore, the organization of some networks does not fit the model It is still a valuable frame of reference

33 Sockets First socket implementation was in 4.1cBSD UNIX in early 80s Spec 1170 incorporates 4.3BSD version POSIX will probably standardize sockets in the not to distant future Compile socket programs with library options –lsocket and –lnsl All socket system calls return –1 on failure and set errno

34 Socket Server socket – Creates a handle (file descriptor) bind – Associates handle with a physical location (port) on the network listen – Sets up a queue size for pending requests accept – Listens for client requests

35 Socket Client socket – Creates a handle (file descriptor) connect – Associates handle with the location (port) of the network server

36 Socket Communications The client and server handles are sometimes called transmission endpoints Once connection is established, client and server can communicate using ordinary read and write calls

37 socket #include int socket(int domain, int type, int protocol); Spec 1170 domain – selects protocol family to be used AF_UNIX – Used on a single UNIX system AF_INET – Used on internet and between remote hosts type – SOCK_STREAM – Reliable 2-way connection oriented typically implemented with TCP SOCK_DGRAM – Connectionless communication using unreliable messages of fixed length, typically implemented with UDP Protocol – Specifies protocol to be used – There is usually only one type so it is usually 0

38 bind SYNOPSIS #include int bind (int s, const struct sockaddr *address, size_t address_len); Spec 1170 s – File descriptor returned by the socket call address_len – Number of bytes returned in the *address structure *address – Contains family name and protocol-specific info struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8] };

39 bind (continued) Bind associates a socket endpoint or handle with a specific network connection Internet domain protocols specify the physical connection by a port number UNIX domain protocols specify the connection by a pathname

40 struct sockaddr Contains family name and protocol specific information

41 struct sockaddr_in The internet domain uses struct sockaddr_in for struct sockaddr sin_family – AF_INET sin_port – is the port number using the network byte ordering sin_addr – INADDR_ANY allows communication from any host sin_zero – an array that fills out the structure so that it has the same size as struct sockaddr

42 listen SYNOPSIS #include int listen (int s, int backlog); Spec 1170 s – File descriptor returned by socket backlog – number of pending client requests allowed

43 sin_port field Represents the port using network byte ordering Machines that use a different byte ordering must do a conversion The macro host to network short (htons) can be used to convert port numbers htons should be used even when not necessary to maintain portability

44 u_open The combination of socket, bind, and listen establishes a handle to monitor communication requests from a well-known port If an attempt is made to write to a pipe or socket that no process has open for read, the write generates a SIGPIPE signal and sets errno to EPIPE The default action of SIGPIPE is to terminate the process – This prevents graceful shutdown Socket implementation of UICI ignores SIGPIPE if default handler is active

45 u_open socket Implementation int u_open(u_port_t port) { int sock; struct sockaddr_in server; if (( u_ignore_sigpipe() != 0) || ((sock = socket(AF_INET, SOCK_STREAM,0)) < 0) return –1; server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((short)port); if((bind(sock,(struct sockaddr *)&server,sizeof(server)) <0) || (listen(sock, MAXBACKLOG < 0)) return –1; return sock; }

46 accept SYNOPSIS #include int accept(int s, struct sockaddr *address, int *address_len); Spec 1170 Parameters are similar to bind, except that accept fills in *address with info about the client making the connection sin_addr holds Internet address of client *address_len – contains number of bytes of the buffer actually filled in by the accept call accept returns file descriptor for communicating with client In parent-server model, server forks a child to handle the request and resumes monitoring the file descriptor Convert sin_addr to a name by calling gethostbyaddr

47 gethostbyaddr SYNOPSIS #include struct hostent *gethostbyaddr(const void *addr, size_t len, int type); Spec 1170 struct hostent includes a field h_name that is a pointer to the official host name On error, gethostbyaddr returns NULL and sets the external integer h_error gethostbyaddr is not thread safe, but gethostbyaddr_r is

48 u_listen socket Implementation int u_listen(int fd, char *hostn) { struct sockaddr_in net_client; int len = sizeof(struct sockaddr); int retval; struct hostent *hostptr; while ( ((retval = accept(fd, (struct sockaddr *)(&net_client), &len)) == -1) && (errno == EINTR) ); if (retval == -1) return retval; hostptr = gethostbyaddr((char *)&(net_client.sin_addr.s_addr), 4, AF_INET); if (hostptr == NULL) strcpy(hostn, "unknown"); else strcpy(hostn, (*hostptr).h_name); return retval; }

49 connect SYNOPSIS #include int connect (int s, struct sockaddr *address, size_t addres_len); Spec 1170 Establishes a link between file descriptor s and a well-known port on the remote server The sockaddr_in structure is filled in as it is with bind

50 gethostbyname SYNOPSIS #include struct hostent *gethostbyname(const char *name); Spec 1170 The host name string is converted to an appropriate Internet address by calling gethostbyname struct hostent includes two members of interest: –h_addr_list is an array of pointers to network addresses used by this host – use the first one h_addr_list[0] –h_length is filled with the number of bytes in the address On error gethostbyname returns NULL and sets the external integer h_error – macros exist to determine error gethostbyname_r is thread safe

51 u_connect socket Implementation (top) int u_connect(u_port_t port, char *hostn) { struct sockaddr_in server; struct hostent *hp; int sock; int retval; if ( (u_ignore_sigpipe() != 0) || !(hp = gethostbyname(hostn)) || ((sock = socket(AF_INET, SOCK_STREAM, 0)) h_addr_list[0], hp->h_length); server.sin_port = htons((short)port); server.sin_family = AF_INET;

52 u_connect Implementation (bottom) while ( ((retval = connect(sock, (struct sockaddr *)&server, sizeof(server))) == -1) && (errno == EINTR) ); if (retval == -1) { close(sock); return -1; } return sock; } Client creates a socket and makes the connection request Client can be interrupted by a signal and loop reinitiates the call Program does not use strncpy for server.sin_addr since the source may have an embedded zero byte Once client and server establish a connection, they exchange information using u_read (read) and u_write (write)

53 Transport Layer Interface (TLI) TLI is an alternative to sockets for doing client server communications Introduced in System V Release 3 in 1986 Implemented on top of STREAMS Compile programs using –lnsl option to access the TLI library

54 TLI Problems More complicated than sockets because it must explicitly allocate space for communication structures by calling t_alloc and deallocate using t_free TLI data structures are in the user area, so they are not available after exec – t_synch copies required information from the user area

55 TLI Error Handling Error handling is more complicated errno is not set directly when an error is encountered TLI provides t_errno to specify errors – t_look examines the status of the communicating channel If problem is the result of system error, TLI sets t_errno to TSYSERR Then, errno contains relevant error information

56 t_open SYNOPSIS #include int t_open(const char *path, int oflag, struct t_info *info); Spec 1170 t_open creates a handle or transmission endpoint *path –/dev/tcp establishes connection oriented –/dev/udp establishes connectionless oflag – Used similar to open system call – typically O_RDWR *info – On successful completion, *info contains info about the underlying protocol – If NULL pointer, t_open does not return any information If successful, t_open returns a communication file descriptor – If not it returns –1 and sets t_errno

57 t_bind SYNOPSIS #include int t_bind (int fildes, const struct t_bind *req, struct t_bind *ret); Spec 1170 Similar to the bind function for sockets Associates a file descriptor with a physical connection (port) fildes – The handle returned by t_open *req – If not a NULL pointer and t_bind is successful, t_bind fills with info about port – struct t_bind contains the following fields: struct netbuf addr; /* same as struct sockaddr_in */ unsigned qlen; /* number of outstanding connections – similar to listen with sockets */ Handling a backlog of requests is complicated in TLI – UICI doesn’t allow them

58 int u_open(u_port_t port) { int fd; struct t_info info; struct t_bind req; struct sockaddr_in server; /* Create a TLI endpoint */ fd = t_open("/dev/tcp", O_RDWR, &info); if (fd < 0) return -1; /* Specify server information with wildcards */ memset(&server, 0, (size_t)sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((short)port); req.addr.maxlen = sizeof(server); req.addr.len = sizeof(server); req.addr.buf = (char *)&server; req.qlen = 1; /* bind the TLI endpoint to port */ if (t_bind(fd, &req, NULL) < 0) return -1; return fd; } u_open TLI Implementation

59 t_listen SYNOPXIX #include int t_listen (int fildes, struct t_call * call); Spec 1170 fildes – Is the handle returned by t_open *call – When successful, t_listen returns 0 and fills the *call structure with information about the connection If not successful t_listen returns –1 and sets t_errno Due to intended generality, struct t_call is complicated TLI uses many data type structures whose size depends on the transport protocol – It is not possible to use automatic variables for these, so TLI allocates them with t_alloc

60 t_alloc SYNOPSIS #include char *t_alloc (int fildes, int struct_type, int fields); Spec 1170 fildes – Is returned by t_open to determine transport protocol or the size of structure that is needed To allocate a struct t_call structure for use by t_listen, use t_alloc with struct_type equal to T_CALL and fields equal to T_ADDR It is necessary to initialize t_call before executing t_listen Once t_listen returns, the server calls t_accept to accept a communications request

61 t_accept SYNOPSIS int t_accept (int fildes, int resfd, struct t_call *call); Spec 1170 Once t_listen returns, the server calls t_accept to accept a communications request The server creates a new file descriptor for the actual communications, so the original file descriptor can be used to listen on another connection fildes – Is the handle returned by the original t_open resfd – Is the handle returned by the second t_open *call – Is the the t_call structure returned by t_listen – It need not be modified before calling t_accept

62 TLI – u_listen (top) int u_listen(int fd, char *hostn) { struct t_call *callptr; struct sockaddr_in *client; struct hostent *hostptr; int newfd; int tret; if ( (callptr = (struct t_call *)t_alloc(fd, T_CALL, T_ADDR)) == NULL) { return -1; }

63 TLI – u_listen (middle) while( ((tret = t_listen(fd, callptr)) < 0) && (t_errno == TSYSERR) && (errno == EINTR) ) ; /* t_listen interrupted and restarted */ if ( (tret < 0) || ((newfd = t_open("/dev/tcp", O_RDWR, NULL)) < 0 ) || (t_bind(newfd, NULL, NULL) < 0 ) || (t_accept(fd, newfd, callptr) < 0) ) { t_free((char *)callptr, T_CALL); return -1; }

64 TLI – u_listen (bottom) client = (struct sockaddr_in *)(callptr->addr).buf; hostptr = gethostbyaddr((char *)&(client->sin_addr.s_addr), 4, AF_INET); if (hostptr == NULL) strcpy(hostn, "unknown"); else strcpy(hostn, hostptr->h_name); t_free((char *)callptr, T_CALL); return newfd;

65 TLI – u_listen Analysis t_listen causes the caller to block until a connection request arrives, there is an error, or an asynchronous event on the communication channel In the case of an asynchronous event, t_error is set to TLOOK – Call t_look to investigate u_listen automatically restarts t_listen when it detects a call was interrupted by a signal If an error occurs, memory allocated by t_alloc should be freed – That may not be necessary for programs that terminate when an error occurs, but here the server may listen again after failures

66 t_connect SYNOPSIS #include int t_connect (int fildes, const struct t_call *sndcall, struct t_call *rcvcall); Spec 1170 The client calls t_open, t_bind, and t_connect sndcall – Is allocated by t_alloc and is filled with information from the server *rcvcall – If connection is successful, t_connect fills *rcvcall structure with information about the connection – If not needed, caller can pass NULL pointer

67 TLI – u_connect (1) int u_connect(u_port_t port, char *inetp) { struct t_info info; struct t_call *callptr; struct sockaddr_in server; struct hostent *hp; int fd; int trynum; unsigned int slptime; fd = t_open("/dev/tcp", O_RDWR, &info); if (fd < 0) return -1;

68 TLI – u_connect (2) /* Create TCP addresses for communication with port */ memset(&server, 0, (size_t)sizeof(server)); server.sin_family = AF_INET; /* Internet address family */ hp = gethostbyname(inetp); /* change name to Internet address */ /* copy Internet address to buffer */ if (hp == NULL) { fprintf(stderr, "gethostbyname returned NULL\n"); return -1; } memcpy(&(server.sin_addr.s_addr), hp->h_addr_list[0], (size_t)hp->h_length); server.sin_port = htons((short)port);

69 TLI – u_connect (3) /* set buffer with destination info */ if (t_bind(fd, NULL, NULL) addr.maxlen = sizeof(server); callptr -> addr.len = sizeof(server); callptr -> addr.buf = (char *)&server; callptr -> opt.len = 0; callptr -> udata.len = 0;

70 TLI – u_connect (4) /* Keep trying until the server is ready */ for (trynum = 0, slptime = 1; (trynum addr.buf = NULL; t_free((char *)callptr, T_CALL); if (trynum >= RETRIES) return -1; return fd; }

71 TLI – u_connect Analysis Queued requests produce a complication If the queue has length 1, connection requests are denied while a previous request is being serviced Sockets avoid the problem with a larger queue length When TLI queue length is greater than 1, the server becomes very complicated A t_accept fails if another connection request is in the queue, so server must listen for all pending connections and queue them before t_accept succeeds UICI avoids this by using queue length 1 – request can fail because server has not yet accepted previous request u_connect retries a connection when it fails After a failed connection attempt, u_connect calls t_rcvdis to receive notification of the rejection

72 TLI – u_connect Analysis (Cont) As with the server, the client uses t_free to free up dynamically allocated memory in case of an error t_free attempts to free all memory referenced by callptr->addr.buff Since that buffer is part of an automatic variable, an error would result Problem is solved here by setting callptr->addr.buf to NULL before calling t_free

73 t_rcv and t_snd SYNOPSIS #include int t_rcv(int fildes, char *buf, unsigned nbytes, int *flags); int t_snd(int fildes, char *buf, unsigned nbytes, int flags); Spec 1170 TLI version of UICI uses t_rcv and t_snd to implement u_read and u_write respectively t_rcv and t_snd are like u_read and u_write except for the extra parameter flags that allows high priority communication

74 STREAMS System V interface between the user and character-oriented device drivers If a program is communicating with a character- oriented device, it is probably using STREAMS Support a variety of services from network protocol suits to device drivers for modems Developed by Dennis Ritchie of ATT in 1982 First commercial versions System V Release 3.0 in 1986 Incomprehensible but unavoidable with device drivers System V socket and TLI interfaces are usually implemented with STREAMS

75 downstream kernel space upstream STREAM Interface user process STREAM head STREAM module device driver User Space

76 Stream Head Entry point into kernel is called stream head Entry point is full-duplex communication channel accessed by file descriptor through system calls open, close, read, write, ioctl, putmsg, and getmsg read – info travels upstream write- info travels downstream

77 Device Drivers Messages are passed from the stream head through an arbitrary number of processing modules to the device driver Device driver has an entry point in the /dev directory Some device drivers correspond to to real physical devices such as speaker or microphone on a workstation Pseudodevice drivers correspond to simulated or pseudodevices

78 Processing Modules Common STREAM processing modules are found in /kernel/strmod They include bufmod, connld, idterm, pipemod, ptem, rpcmod, sockmod, timod, tirdwr, and ttcompat In theory programmers can develop STREAM modules, but superuser privileges are needed to install the modules

79 List Modules #include int ioctl(int fd, I_LIST, struct str_list *mlist) The I_LIST option of ioctl lists the modules on a stream The fd parameter is the open fd for the stream *mlist contains module names

80 Open Modules list_stream_modules – lists modules and drivers open of fd Returns –1 on error or 0 if successful

81 Module Example $ who robbinspts/1Oct 9 09:26(vip) robbinspts/2Oct 9 09:26(vip) if((fd=open(“/dev/pts/2”, O_RDONLY))==-1) perror(“Could not open /dev/pts/2”); elseif(list_stream_modules(fd)==-1) fprintf(stderr,”Could not list command modules \n”); Module(s) on the stream: ttcompat ldterm ptem pts

82 Module Functions ttcompat and ldterm –provide terminal line discipline –make the stream appear to be coming from a terminal –ldterm handles delete character, line buffering, etc –ttcompat allows older versions of ioctl to work ptem – Provides terminal-like control such as tracking window size and ignoring baud rate or parity pts – The underlying pseudoterminal device driver

83 Pipes System V implements pipes by connecting two stream heads stream head fd[1] fd[0] user space kernel space

84 Pipe Example 1 if (pipe (fd) == -1) perror(“bad pipe”); else if (list_stream_modules(fd[1]) == -1) fprintf(stderr, “Could not list modules\n”); Should indicate that there are no modules or device drivers on the stream

85 Pipe Example 2 if (pipe (fd) == -1) return –1; if (ioctl(fd[0], I_PUSH, “ldterm”) == -1) return –1; if (ioctl(fd[0], I_PUSH, “ttcompat”) == -1) return –1; Makes a pipe appear to be a terminal by pushing ttcompat and ldterm on the stream fd[0] handles the delete character and is line- buffered

86 Messages STREAM modules pass information upstream and downstream in the form of messages of type struct strbuf struct strbuf { intmaxlen;/* no. of bytes in buffer */ int len;/* no. of bytes returned */ char*buf;/* pointer to data */

87 STREAM Module Each STREAM module consists of a read queue, write queue, and processing entry points Read queue holds messages moving upstream Write queue holds messages that are moving downstream open – performs initialization close – performs shutdown activities prior to module’s removal from stream put – module transfers a message to another module’ pool service – a module can either process a message immediately or place message in the queue for later processing by service --- deferred processing of messages

88 entry points write open queue close put read service queue STREAM Module

89 connld/fattach if (pipe(fd) == -1) perror (“Bad pipe”); else if (ioctl(fd[1], I_PUSH, “connld”) == -1) perror (“Could not push connld”); STREAMS uses connld to do connection-oriented communication After pushing connld processing module on the stream, attach a name to fd[1] with fattach fattach attaches STREAMS file descriptor to a pathname

90 Pathname Pathname corresponds to an existing file with privileges set so that both client and server can access it Pathname serves as the well-known port referenced by the client When server does an I_RECVFD ioctl on the original file descriptor, it blocks until another process does an open on the corresponding filename open returns a file descriptor that the client can use for communication I_RECVFD ioctl returns a new file descriptor to the server so it can communicate with the client

91 Pushing connld fd[1] fd[0] user space stream head stream head kernel space connld

92 STREAM – u_open int u_open(u_port_t port) { char buffer[MAX_CANON]; int mtpoint; int fd[2]; sprintf(buffer,”/tmp/streams_uici_%d”,(int)port); unlink(buffer); if((mtpoint = creat(buffer, MTMODE)) != -1 && (close(mtpoint) != -1) && (pipe(fd) != -1 && (ioctl(fd[1], I_PUSH,”connld”) != -1) && (fattach(fd[1],buffer) != -1)) return fd[0] close (fd[0]); close (fd[1]); return –1; }

93 STREAMS – u_listen int u_listen (int fd, char *hostn) { mystrrecvfd conversation_info; int retval; while (((retval = ioctl (fd,I_RECFD,&conversation_info)) == -1) && (errno = EINTR)); if (retval == -1) return –1; *hostn = 0; return conversation_info.f.fd; }

94 STREAMS – u_connect int u_connect(u_port_t port, char *hostn) { char buffer[MAX_CANON]; sprintf(buffer,”/temp/streams_uici_%d”, (int)port); return open(buffer, O_RDWR); }


Download ppt "Client-Server Communications Servers provide services to clients over a network Most LANs have file servers to manage common disk space This makes it easier."

Similar presentations


Ads by Google