CS241 System ProgrammingDiscussion Section 11April 24 – April 27Outlinez Connectionless Socket Programmingz Connectionless Library Functionsz UICI UDP Implementationz MP5 ClarificationsRecall:Implementation of u_openint u_open(u_port_t port) {int error;struct sockaddr_in server;int sock;int true = 1;if ((u_ignore_sigpipe() == -1) ||((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1))return -1;if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&true,sizeof(true)) == -1) {error = errno;while ((close(sock) == -1) && (errno == EINTR));errno = error;return -1;}server.sin_family = AF_INET;server.sin_addr.s_addr = htonl(INADDR_ANY);server.sin_port = htons((short)port);if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) == -1) ||(listen(sock, MAXBACKLOG) == -1)) {error = errno;while ((close(sock) == -1) && (errno == EINTR));errno = error;return -1;}return sock;}Implementation of u_openudpint u_openudp(u_port_t port) {int error;int one = 1;struct sockaddr_in server;int sock;if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)return -1;if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {error = errno;r_close(sock);errno = error;return -1;}if (port > 0) {server.sin_family = AF_INET;server.sin_addr.s_addr = htonl(INADDR_ANY);server.sin_port = htons((short)port);if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == -1) {error = errno;r_close(sock);errno = error;return -1;} } return sock;}z Returns file descriptor if successfulz portz port=0 means client (bind does not occur)z port=“well-known port” means serveru_open vs. u_openudpz Only a server needs to bind the socketz No SIGPIPE problemz A write to a pipe (e.g. TCP socket) generates a SIGPIPE signal when there are no active readers.z UDP provides no information about active readers.z UDP datagram is “sent correctly” when copied into network buffer (no error detection).POSIX sendtossize_t sendto(int socket, const void *message, size_tlength, int flags, const struct sockaddr *dest_addr,socklet_t dest_len);z sends length bytes, from data pointed to by messagez dest_addr contains remote host address and remote port number.z Returns the number of bytes actually sent out if successful, -1 with errno set if unsuccessfulz Datagram includes originating port number and source host addressz If connected, still uses dest_addr for destonationPOSIX recvfromssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, structsockaddr *restrict address, socklen_t *restrict address_len);z Must associate socket with a port using bind or sendtoz Blocks until a datagram becomes availablez Unassociated socket causes indefinite hangz buffer is filled with received dataz address is filled with address of senderz Must fill in address_len before callingz Why???z Returns the number of bytes actually read if successful, -1 with errno set if unsuccessfulImplementation of u_sendtohostssize_t u_sendtohost(int fd, void *buf, size_t nbytes, char *hostn,u_port_t port) {struct sockaddr_in remote;if (name2addr(hostn, &(remote.sin_addr.s_addr)) == -1) {errno = EINVAL;return -1;}remote.sin_port = htons((short)port);remote.sin_family = AF_INET;return u_sendto(fd, buf, nbytes, &remote);}z Used to initiate communication with a remote host(specified by hostn and port)Implementation of u_sendtossize_t u_sendto(int fd, void *buf, size_t nbytes, u_buf_t *ubufp) {int len;struct sockaddr *remotep;int retval;len = sizeof(struct sockaddr_in);remotep = (struct sockaddr *)ubufp;while (((retval = sendto(fd, buf, nbytes, 0, remotep, len)) == -1)&& (errno == EINTR)) ; return retval;}z Used to send a reply to a message received using u_recvfrom or u_recvfromtimedz u_buf_t (struct sockaddr_in) structure that was filled by a previouscall to u_recvfrom or u_recvfromtimedz Basically a restarting sendtoz Returns a nonnegative integer corresponding to a socket file descriptor if successful, -1 with errno set if unsuccessfulImplementation of u_recvfromssize_t u_recvfrom(int fd, void *buf, size_t nbytes, u_buf_t *ubufp) {int len;struct sockaddr *remote;int retval;len = sizeof (struct sockaddr_in);remote = (struct sockaddr *)ubufp;while (((retval = recvfrom(fd, buf, nbytes, 0, remote, &len)) == -1)&& (errno == EINTR)) ; return retval;}z Restarting recvfromz Returned sender information fills the u_buf_t *ubufp parameterz Can call u_sendto using this u_buf_tz Returns -1 with errno set if unsuccessful. Note: return value of 0 corresponds to datagram of length 0 (valid).Recall: UDP is unreliablez Datagrams can be lost without any errors generated.z UDP-based protocols for providing reliability use request-reply or request-reply-acknowledge protocolsz Receiver must not block indefinitelyz Which brings us to...<next slide>Implementation of u_recvfromtimedssize_t u_recvfromtimed(int fd, void *buf, size_t nbytes, u_buf_t *ubufp,double seconds) {int len;struct sockaddr *remote;int retval;struct timeval timedone;timedone = add2currenttime(seconds);if (waitfdtimed(fd, timedone) == -1)return (ssize_t)(-1);len = sizeof (struct sockaddr_in);remote = (struct sockaddr *)ubufp;while (((retval = recvfrom(fd, buf, nbytes, 0, remote, &len)) == -1)&& (errno == EINTR)) ; return retval;}z If successful, returns the number of bytes written into buf z If timeout occurs, returns -1 and sets errno to ETIMEz add2currenttime: converts the time interval into an ending timez waitfdtimed: Implemented using select – times out after specified number of secondsu_recvfromtimedz Suppose you call u_recvfromtimed with a timeout of 2 seconds and 10 signals come in 1 second apart. When does u_recvfromtimed time out if no data arrives?u_recvfromtimedz Suppose you call u_recvfromtimed with a timeout of 2 seconds and 10 signals come in 1 second apart. When does u_recvfromtimed time out if no data arrives?z Answer:2 seconds after it’s called (timeout is independent of number of times it needs to restart – uses end time computed from add2currenttime)UICI UDP –Receiver host informationz Functions for examining the receiver host information (as filled in the u_buf_t structure)void u_gethostname(u_buf_t *ubufp, char *hostn, int hostnsize)void u_gethostinfo(u_buf_t *ubufp, char *info, int infosize)int u_comparehost(u_buf_t *ubufp, char *hostn, u_port_t port)Implementation of addr2namevoid addr2name(struct in_addr addr, char *name, int namelen) {struct hostent *hostptr;hostptr = gethostbyaddr((char *)&addr, 4, AF_INET);if (hostptr == NULL)strncpy(name, inet_ntoa(addr),
View Full Document