back to Communication Nezer J. Zaidenberg (Evyatar’s version) Remember to read Beej’s guides what we should know using TCP sockets socket(2), close(2) bind(2)+listen(2)+accept(2) connect(2) send(2)+recv(2) select(2) Protecting recv(2) unless we select(2) before recv(2) we end up with process that does busy waiting (check.) Therefore, all our recv’s should be protected by select even if alone. Busy Waiting.. Datagram sockets Just forget everything you learned about TCP sockets. DATAGRAM SOCKETS Datagram sockets are CONNECTIONLESS. (there are connected udp sockets in Linux but we will not discuss) NO CONNECT(2), LISTEN(2), ACCEPT(2) So what do we have left? Server still calls socket(2) and bind(2) to catch a port. Client still calls socket(2) No connection - problem when we used TCP sockets we called send(2)+recv(2) and we knew who to send to because this was already in the socket file descriptor.... when we don’t have connection this information is no longer available to us Sendto(2) + recvfrom(2) works like send(2)+recv(2) but also specify the address we send and recv from. • SEND(2) BSD System Calls Manual SEND(2) • NAME • • sendto -- send a message from a socket SYNOPSIS • #include <sys/socket.h> • ssize_t • sendto(int socket, const void *buffer, size_t length, int flags, const struct sockaddr *dest_addr, socklen_t dest_len); • RECV(2) BSD System Calls Manual • NAME • • recvfrom-- receive a message from a socket SYNOPSIS • #include <sys/socket.h> • ssize_t • RECV(2) recvfrom(int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, socklen_t *restrict address_len); Explaining both functions return bytes received while holding max buffer size as argument. The additional sockaddr is the address we “would connect to”. As always we will “inherit” and use sockaddr_in or sockaddr_un. silly UDP talker - from beej • int main(int argc, char *argv[]) • { • int sockfd; • struct addrinfo hints, *p; • int rv,numbytes; • memset(&hints, 0, sizeof hints); • hints.ai_family = AF_UNSPEC; • hints.ai_socktype = SOCK_DGRAM; Talker continued Later • getaddrinfo(argv[1], SERVERPORT, &hints, &p) • sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol) • sendto(sockfd, argv[2], strlen(argv[2]), 0, p->ai_addr, p->ai_addrlen) • • freeaddrinfo(p); • printf("talker: sent %d bytes to %s\n", numbytes, argv[1]); • close(sockfd); • return 0; • } Please examine Beej for UDP listener http://www.beej.us/guide/bgnet/output/html/ multipage/clientserver.html#datagram UNIX domain sockets As we said previously very similar to Internet sockets We don’t use ports. instead we use path to find the right application. (we create a dummy “file” as address) We will not cover the commands again but go over change list UDS changes in socket we use AF_UNIX for domain In bind we use struct sockaddr_un we use AF_UNIX for domain we use path instead of port UDS changes no changes in listen(2) accept(2) send(2) recv(2) close(2) (accept return address as sockaddr_un) sendto(2) and recvfrom(2) use struct sockaddr_un instead of struct sockaddr_in UDS bind example • local.sun_family = AF_UNIX; • strcpy(local.sun_path, SOCK_PATH); • unlink(local.sun_path); • len=strlen(local.sun_path)+sizeof(local.sun_family) ; • if (bind(s, (struct sockaddr *)&local, len) == -1) { perror("bind"); exit(1); • • } about example in the above example unlink(2) deletes the file if it exist (from previous run) otherwise bind will fail. full example - http://beej.us/guide/bgipc/output/html/ multipage/unixsock.html good luck with HW1 note regarding HW1 you have been requested to handle connections in a child process. After accept(2) you should fork(2) and use the new child process to handle the connection. (father can close(2) newfd) Child exit(2) when the connection is closed(2) And if we still have time… socketpair(2) socketpair(2) system call create two sockets that are already connected! This is useful way for father and child process to communicate • SOCKETPAIR(2) • NAME • socketpair -- create a pair of connected sockets • SYNOPSIS • #include <sys/socket.h> • int • socketpair(int domain, int type, int protocol, int socket_vector[2]); Explaining the first 3 parameters are same as socket(2) and define the socket type to be created the last parameter is an int array with file descriptors of the connected sockets return value is just success/fail usage example • int sv[2]; /* the pair of socket descriptors */ • if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1) { • perror("socketpair"); • exit(1); • }