Caution
- The sockets API is idiomatic C
- Be careful
- Check errors
Connection Lifecycle
- Get an IP address (usually by looking up a hostname in DNS)
- Create a socket using the address, protocol, and port number
- Bind the socket to the remote host
- Loop over open sockets
- Write data
- Read data on ready sockets
- Deallocate dynamic resources
Lookup a hostname
#include < netdb.h>
main() {
struct addrinfo hints;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = 0;
hints.ai_protocol = 0;
struct addrinfo *results;
int e = getaddrinfo("vlab00.cs.usfca.edu", "2221", &hints,
&results);
if (e != 0) {
printf("getaddrinfo: %s\n", gai_strerror(e));
exit(-1);
}
}
Make a socket File Descriptor
#include < sys/socket.h>
struct addrinfo *r;
int fd;
for (r = results; r != NULL; r = r->ai_next) {
fd = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
if (fd == -1)
continue;
if (connect(fd, r->ai_addr, r->ai_addrlen) != -1)
break;
close(fd);
}
freeaddrinfo(results);
if (r == NULL) {
printf("Could not connect\n");
exit(-1);
}
Connect socket and addrinfo
if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
Write on the connected socket
if (write(fd, "hello", 6) == 6)
Read on the connected socket
char buf[32];
if (read(fd, buf, 32) != -1)
Deallocate resources
close(fd);
freeaddrinfo(results);
Key Concepts
- A socket file descriptor is just an
int
- File descriptors can be used with
read()
and write()
system calls
- Clients: lookup, socket, connect, read/write
- Servers: socket, bind, recvfrom (UDP)
- Check errors. Use
perror()