CS241 System ProgrammingOutlineSocketSocket Functionssocketbindconnectlistenacceptsend and sendtorecv and recvfromclose and shutdownImplementation of u_openSlide 14Implementation of u_acceptImplementation of u_connectSlide 17ReferenceHTTPHTTP (continued)Sample HTTP exchangeSlide 22HTTP exchange in MP5Communications in MP5SummaryCS241 System ProgrammingDiscussion Section 11April 17 – April 20OutlineSocket ProgrammingLibrary FunctionsUICI ImplementationHypertext Transfer ProtocolSocketStandard APIs for sending and receiving data across computer networksIntroduced by BSD operating systems in 1983POSIX incorporated 4.3BSD sockets and XTI in 2001#include <sys/socket.h>Socket Functionssocketbindconnectlistenacceptsend, sendtorecv, recvfromclose, shutdownsocketint socket(int domain, int type, int protocol);Creates a communication endpointParametersdomain: AF_INET (IPv4)type: SOCK_STREAM (TCP) or SOCK_DGRAM (UDP)protocol: 0 (socket chooses the correct protocol based on type)Returns a nonnegative integer corresponding to a socket file descriptor if successful, -1 with errno set if unsuccessfulbindint bind(int socket, const struct sockaddr *address, socklen_t address_len);Associates the socket with a port on your local machinestruct sockaddr_in used for struct sockaddrsa_family_t sin_family; /* AF_INET */in_port_t sinport; /* port number */struct in_addr sin_addr; /* IP address */Returns 0 if successful, -1 with errno set if unsuccessfulconnectint connect(int socket, const struct sockaddr *address, socklen_t address_len);Establishes a link to the well-known port of the remote serverInitiates the TCP 3-way handshakeCannot be restarted even if interruptedReturns 0 if successful, -1 with errno set if unsuccessfullistenint listen(int socket, int backlog);Puts the socket into the passive state to accept incoming requestsInternally, it causes the network infrastructure to allocate queues to hold pending requestsbacklog: number of connections allowed on the incoming queuebind should be called beforehandReturns 0 if successful, -1 with errno set if unsuccessfulacceptint accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);Accepts the pending requests in the incoming queue*address is used to return the information about the client making the connection. sin_addr.s_addr holds the Internet addresslisten should be called beforehandReturns nonnegative file descriptor corresponding to the accepted socket if successful, -1 with errno set if unsuccessfulsend and sendtoint send(int socket, const void *msg, int len, int flags);int sendto(int socket, const void *msg, int len, int flags, const struct sockaddr *to, socklet_t tolen);sends data pointed by msgsendto is used for unconnected datagram sockets. If used in connection-mode, last two parameters are ignored.Returns the number of bytes actually sent out if successful, -1 with errno set if unsuccessfulrecv and recvfromint recv(int socket, void *buf, int len, int flags);int recvfrom(int socket, void *buf, int len, int flags, const struct sockaddr *from, socklet_t fromlen);receives data into the buffer bufrecvfrom is used for unconnected datagram sockets. If used in connection-mode, last two parameters are ignored.Returns the number of bytes actually read if successful, -1 with errno set if unsuccessfulclose and shutdownint close(int socket);int shutdown(int socket, int how);closePrevents any more reads and writessame function covered in file systemsshutdownprovides a little more controlhow0 – Further receives are disallowed1 – Further sends are disallowed2 – same as closeReturns 0 if successful, -1 with errno set if unsuccessfulImplementation 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 = s ocket(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; } /* continued on the next page */setsockoptSets the options on socketsSO_REUSEADDR permits the server to be restarted immediatelyu_ignore_sigpipeSets SIGPIPE to be ignored. It terminates the process by defaultImplementation of u_open 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;}htoln, htonsConverts the address and port number fields to network byte orderImplementation of u_acceptint u_accept(int fd, char *hostn, int hostnsize) { int len = sizeof(struct sockaddr); struct sockaddr_in netclient; int retval; while (((retval = accept(fd, (struct sockaddr *)(&netclient), &len)) == -1) && (errno == EINTR)) ; if ((retval == -1) || (hostn == NULL) || (hostnsize <= 0)) return retval; addr2name(netclient.sin_addr, hostn, hostnsize); return retval;}addr2nameConverts the address to an ASCII host nameImplementation of u_connectint u_connect(u_port_t port, char *hostn) { int error; int retval; struct sockaddr_in server; int sock; fd_set sockset; if (name2addr(hostn,&(server.sin_addr.s_addr)) == -1) { errno = EINVAL; return -1; } server.sin_port = htons((short)port); server.sin_family = AF_INET; if ((u_ignore_sigpipe() == -1) || ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)) return -1;name2addrConverts the host name into a binary address and stores it to its second parameterImplementation of u_connect if (((retval = connect(sock, (struct sockaddr *)&server, sizeof(server))) == -1) && ((errno == EINTR) || (errno == EALREADY))) { /* asynchronous */ FD_ZERO(&sockset); FD_SET(sock, &sockset); while (((retval = select(sock+1, NULL, &sockset, NULL, NULL)) == -1) && (errno == EINTR)) { FD_ZERO(&sockset); FD_SET(sock, &sockset); } } if (retval == -1) { error = errno; while ((close(sock) == -1) && (errno == EINTR)); errno = error;
View Full Document