Professional Documents
Culture Documents
struct in_addr { in_addr_t s_addr; }; struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port; /* 32-bit IPv4 address */ /* network byte ordered */
/* /* /* /*
length of structure (16) */ AF_INET */ 16-bit TCP/UDP port number */ network byte ordered */
char sin_zero[8];
struct in_addr { in_addr_t s_addr; }; struct sockaddr_in { uint8_t sin_len; sa_family_t sin_family; in_port_t sin_port;
/* /* /* /*
length of structure (16) */ AF_INET */ 16-bit TCP/UDP port number */ network byte ordered */
char sin_zero[8];
#define SIN6_LEN
struct sockaddr_in6 { uint8_t sin6_len; sa_family_t sin6_family; in_port_t sin6_port; uint32_t sin6_flowinfo; struct in6_addr sin6_addr; uint32_t sin6_scope_id;
/* length of this struct (28) */ /* AF_INET6 */ /* transport layer port# */ /* network byte ordered */ /* flow information, undefined */ /* IPv6 address */ /* network byte ordered */ /* set of interfaces for a scope */ };
Value-Results arguments
Value-Result arguments
Fixed size data structure Kernel informs how much information was stored
Internet Protocols
# include <netinet/in.h> uint16_t htons(uint16_t host16bitvalue) ; uint32_t htonl(uint32_t host32bitvalue) ; Both return: value in network byte order uint16_t ntohs(uint16_t net16bitvalue) ; uint32_t ntohl(uint32_t net32bitvalue) ; Both return: value in host byte order
Operates on multibyte fileds, without interpreting the data, and without asuming that the data is a null-terminated C string bzero, bcopy, bcmp memset, memcpy, memcmp
#include <arpa/inet.h> int inet_aton(const char *strptr, struct in_addr *addrptr); Returns: 1 if string was valid, 0 on error in_addr_t inet_addr(const char *strptr); Returns: 32-bit binary network byte ordered IPv4 address; INADDR_NONE if error
read, write
It may read/write less than needed due to finite buffer call function Only if write is nonblocking
read, write
lib/readn.c 1 #include "unp.h" 2 ssize_t /* Read "n" bytes from a descriptor. */ 3 readn(int fd, void *vptr, size_t n) 4{ 5 size_t nleft; 6 ssize_t nread; 7 char *ptr; 8 ptr = vptr; 9 nleft = n; 10 while (nleft > 0) { 11 if ( (nread = read(fd, ptr, nleft)) < 0) { 12 if (errno == EINTR) 13 nread = 0; /* and call read() again */ 14 else 15 return (-1); 16 } else if (nread == 0) 17 break; /* EOF */ 18 nleft -= nread; 19 ptr += nread; 20 } 21 return (n - nleft); /* return >= 0 */ 22 }
read, write
lib/writen.c 1 #include "unp.h" 2 ssize_t /* Write "n" bytes to a descriptor. */ 3 writen(int fd, const void *vptr, size_t n) 4{ 5 size_t nleft; 6 ssize_t nwritten; 7 const char *ptr; 8 ptr = vptr; 9 nleft = n; 10 while (nleft > 0) { 11 if ( (nwritten = write(fd, ptr, nleft)) <= 0) { 12 if (nwritten < 0 && errno == EINTR) 13 nwritten = 0; /* and call write() again */ 14 else 15 return (-1); /* error */ 16 } 17 nleft -= nwritten; 18 ptr += nwritten; 19 } 20 return (n); 21 }
read, write
1 # include "unp.h" 2 static int read_cnt; 3 static char *read_ptr; 4 static char read_buf[MAXLINE]; 5 static ssize_t 6 my_read(int fd, char *ptr) 7{ 8 if (read_cnt <= 0) { 9 again: 10 if ( (read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) { 11 if (errno == EINTR) 12 goto again; 13 return (-1); 14 } else if (read_cnt == 0) 15 return (0); 16 read_ptr = read_buf; 17 } 18 read_cnt--; 19 *ptr = *read_ptr++; 20 return (1); 21 }
22 ssize_t 23 readline(int fd, void *vptr, size_t maxlen) 24 { 25 ssize_t n, rc; 26 char c, *ptr; 27 ptr = vptr; 28 for (n = 1; n < maxlen; n++) { 29 if ( (rc = my_read(fd, &c)) == 1) { 30 *ptr++ = c; 31 if (c == '\n') 32 break; /* newline is stored, like fgets() */ 33 } else if (rc == 0) { 34 *ptr = 0; 35 return (n - 1); /* EOF, n - 1 bytes were read */ 36 } else 37 return (-1); /* error, errno set by read() */ 38 } 39 *ptr = 0; /* null terminate like fgets() */ 40 return (n); 41 } 42 ssize_t 43 readlinebuf(void **vptrptr) 44 { 45 if (read_cnt) 46 *vptrptr = read_ptr; 47 return (read_cnt); 48 }
read, write
isfdtype
Function socket
int socket ( int family, int type, int protocol) return > 0 if OK, -1 if error
Returns socket descriptor (small positive integer), similar to UNIX file descriptor, to be used perform functions on the socket such as read, write and close
socket
#include <sys/socket.h>
int socket (int family, int type, int protocol); Returns: non-negative descriptor if OK, -1 on error
Socket Function
Parameters:
family: specifies the protocol family: AF_INET for IPv4 AF_INET6 for IPv6 AF_UNIX ou AF_LOCAL - Unix domain socket
type: specifies transport protocol: SOCK_STREAM: stream socket for TCP SOCK_DGRAM: datagram socket for UDP
protocol: usually set to zero
socket Function
Combination of interest
Family AF_INET AF_UNIX Type SOCK_STREAM SOCK_STREAM SOCK_DGRAM SOCK_DGRAM
Exemple: sockfd = socket(AF_INET, SOCK_STREAM, 0), creates an IPv4 socket to be used by TCP
Connect Function
int connect ( int sockfd, const struct sockaddr *servaddr, int addrlen)
Used for establishing a connection:three-way handshake sockfd: return parameter of socket() servaddr: data structure initiated with remote socket identifications (remote IP address, remote port number) For a client TCP, it is not necessary to perform bind: the kernel chooses the local port ephemeral port number and the source IP number if necessary Chosen in a way to avoid conflict of use of port
connect
#include <sys/socket.h> int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen); Returns: 0 if OK, -1 on error
errors
timeout erro ETIMEDOUT, 75 seconds, configurable If the answer to a SYN segment is an RST one error ECONNREFUSED no process listening to the port Destination unreachable (ICMP), soft error, tries for 75 seconds (4.4 BSD)
Bind Function
int bind(int sockfd, (struct sockaddr)* myaddr, int socklen) return 0 if OK, -1 if error
bind a local protocol address given by the structure myaddr to a socket (sockfd) The application can let the kernel chooses the IP address and the port number;
If a host has more than one IP, then the kernel can choose one Ephemeral port numbers are chosen to avoid conflict with other socket To let the kernel chooses the IP address the constant INADDR_ANY should be assigned to the IP address myaddr To let the kernel chooses an ephemeral port number the constant zero should be set to the corresponding field of myaddr: *myaddr.sin_port = 0; *myaddr.sin_addr.s_addr = INADDR_ANY
bind
#include <sys/socket.h> int bind (int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); Returns: 0 if OK, -1 on error
Bind performed by TCP server restricts the socket to receiving incoming client connection destined only to that IP address
bind
Listen Function
int listen (int sockfd, (struct sockaddr) * myaddr, int backlog) return 0 if OK, -1 if error
An active (client) socket is one that called connect com o socket, starting a 3-way handshake with a remote host; An applications (server) which calls listen, makes an unconnected socket a passive one meaning that the kernel must accept incoming connection requests directed to this socket. CLOSED LISTEN
Clients call connect while servers call listen followed by accept The backlog parameter indicates the total size of two queues: the complete queue (ESTABLISHED state) and the incomplete connection queue (SYN_RVCD state)
listen
listen
listen
listen
accept Function
int accept (int sockfd, (struct sockaddr) * cliaddr, int * socklen) returns nonnegative descriptor if OK, -1 if error
Called by a TCP server to return the next completed connection from the front of the completed connection queue. If the queue is empty the process is oput to sleep
aadrlen is a value-result argument and it returns the size of the structure pointed to by cliaddr, i.e., the number of bytes stored by the kernel in the socket address structure.
fork - exec
# include <unistd.h> pid_t fork(void); Returns: 0 in child, process ID of child in parent, -1 on error
Fork is called once but it returns twice. The return value tell the process whether it is a parent or a child It returns once to the calling process (parent) with a return value that is the process ID of the newly created process (child) It returns once in the child, with a return value of zero (0) All the descriptors opened by the parent before the fork are shared with the child after the fork. connected sockts aer an accept and a fork is shared with the Two uses of fork: a process makes a copy of itself (fork) and a process executes another program (fork e exec)
fork - exec
#include <unistd.h> int execl (const char *pathname, const char *arg0, ... /* (char *) 0 */ ); int execv (const char *pathname, char *const argv[ ]); int execle (const char *pathname, const char *arg0, ... /* (char *) 0, char *const envp[ ] */ ); int execve (const char *pathname, char *const argv[ ], char *const envp[ ]); int execlp (const char *filename, const char *arg0, ... /* (char *) 0 */ );
fork - exec
Concurrent server
Concurrent server (iterative server) one server, several connections. Concurrent server serves several active connections. Server performers a fork to create a child to handle the client request After accept, the server calls fork and the child serves the client (on connfd, the connected socket) and the parent waits for another connection (on listenfd, the listening socket)
Concurrent server
Connect returns a brand new socket descriptor for the connection to be established with the TCP client. The return of a connect makes a socket a connected socket. On closing a socket only the specific connection (socket) is closed, the server remains listening to new socket connection request
Concurrent server
A close performed by the server does not imply in terminating the connection, a FYN is sent only when the number of reference to the descriptor in the file table is zero when a child is created the number of reference is incremented by one. If a server does not close the socket none of the children connections will be closed since the number of reference will never be zero and server runs out of descriptor
Concurrent server
pid_t pid; int listenfd, connfd; listenfd = Socket( ... ); /* fill in sockaddr_in{ } with server's well-known port */ Bind(listenfd, ... ); Listen(listenfd, LISTENQ); for ( ; ; ) { connfd = Accept (listenfd, ... ); /* probably blocks */ if( (pid = Fork()) == 0) { Close(listenfd); /* child closes listening socket */ doit(connfd); /* process the request */ Close(connfd); /* done with this client */ exit(0); /* child terminates */ } Close(connfd); /* parent closes connected socket */ }
Concurrent server
Concurrent server
Concurrent server
close
#include <unistd.h> int close (int sockfd); Returns: 0 if OK, -1 on error
connect not followed by bind After calling bind with 0 srgument TCP server performs a bind in a wildcard port