CS241 System ProgrammingOutlineRecall: Implementation of u_openImplementation of u_openudpu_open vs. u_openudpPOSIX sendtoPOSIX recvfromImplementation of u_sendtohostImplementation of u_sendtoImplementation of u_recvfromRecall: UDP is unreliableImplementation of u_recvfromtimedu_recvfromtimedSlide 14UICI UDP – Receiver host informationImplementation of addr2nameImplementation of name2addrImplementation of u_gethostnameImplementation of u_gethostinfoImplementation of u_comparehostUDP vs. TCPMP5 ClarificationsMP5 Datagram ExampleSummaryCS241 System ProgrammingDiscussion Section 12April 24 – April 27OutlineConnectionless Socket ProgrammingConnectionless Library FunctionsUICI UDP ImplementationMP5 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;}Returns file descriptor if successfulportport=0 means client (bind does not occur)port=“well-known port” means serveru_open vs. u_openudpOnly a server needs to bind the socketNo SIGPIPE problemA write to a pipe (e.g. TCP socket) generates a SIGPIPE signal when there are no active readers.UDP provides no information about active readers.UDP datagram is “sent correctly” when copied into network buffer (no error detection).POSIX sendtossize_t sendto(int socket, const void *message, size_t length, int flags, const struct sockaddr *dest_addr, socklet_t dest_len);sends length bytes, from data pointed to by messagedest_addr contains remote host address and remote port number.Returns the number of bytes actually sent out if successful, -1 with errno set if unsuccessfulDatagram includes originating port number and source host addressIf connected, still uses dest_addr for destonationPOSIX recvfromssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, socklen_t *restrict address_len);Must associate socket with a port using bind or sendtoBlocks until a datagram becomes availableUnassociated socket causes indefinite hangbuffer is filled with received dataaddress is filled with address of senderMust fill in address_len before callingWhy???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);}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;}Used to send a reply to a message received using u_recvfrom or u_recvfromtimedu_buf_t (struct sockaddr_in) structure that was filled by a previouscall to u_recvfrom or u_recvfromtimedBasically a restarting sendtoReturns 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;}Restarting recvfromReturned sender information fills the u_buf_t *ubufp parameterCan call u_sendto using this u_buf_tReturns -1 with errno set if unsuccessful. Note: return value of 0 corresponds to datagram of length 0 (valid).Recall: UDP is unreliableDatagrams can be lost without any errors generated.UDP-based protocols for providing reliability use request-reply or request-reply-acknowledge protocolsReceiver must not block indefinitelyWhich 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;}If successful, returns the number of bytes written into buf If timeout occurs, returns -1 and sets errno to ETIMEadd2currenttime: converts the time interval into an ending time waitfdtimed: Implemented using select – times out after specified number of secondsu_recvfromtimedSuppose you call u_recvfromtimed with a timeout of 2 seconds and 10 signals come
View Full Document