Blocking I/O: On A Network Socket¶
Opening a Network Connection¶
Even more than a file, network connections are tedious
Determine destination address: local/remote? (⟶ do I send it to address on local net, or do I send it to my net’s gateway?)
Formulate IP packet
Setup DMA on network hardware
Wait for interrupt
Start transmission timeout
… (you get the point) …
⟶ a job for an Operating System
Abstractions¶
What do we read?
Bytes from a network connection
Addresses depend on network type (TCP/IP is just one out of many)
⟶ Socket abstraction!
How do we read that? In the case of TCP …
Don’t want to … blah interrupt, DMA, blah … want none of that
Only want to connect to peer/server
Only want to read data
Simplicity¶
System call:
socket()
System call:
connect()
System call:
read()
System call:
write()
System call:
close()
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
// allocate space (in kernel) for a TCP connection. the handle to
// it is a FILE DESCRIPTOR, again.
int fd = socket(AF_INET, SOCK_STREAM, 0);
// error handling
if (fd == -1) {
perror("socket()");
exit(1);
}
// connect to peer/server. fill in address structure first.
{
int error;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(1234);
inet_aton("127.0.0.1", &addr.sin_addr);
// this sends out packets via network hardware, does all the
// tedious timeout handling, DMA, and whatnot.
error = connect(fd, (struct sockaddr*)&addr, sizeof(addr));
// error handling
if (error == -1) {
perror("connect()");
exit(1);
}
}
// allocate buffer, and *read* in a loop until done. NOTE THIS IS
// THE SAME AS WITH FILES: "Everything is a file!".
char buffer[16];
while (1) {
ssize_t nbytes_read = read(fd, buffer, sizeof(buffer));
if (nbytes_read == 0) // end-of-file (EOF) -> done
break;
write(STDOUT_FILENO, buffer, nbytes_read);
}
// free resources
close(fd);
return 0;
}
Build, Run, Look¶
$ gcc -o read-network read-network.c
Client |
Server (start first) |
---|---|
$ strace ./read-network
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(1234), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
read(3,
⟶ Blocking system call: nothing there to read |
$ nc -l -p 1234
|
... "hallo du!\n", 16) = 10
write(1, "hallo du!\n", 10hallo du!
) = 10
read(3,
⟶ Wakes up to read “ |
hallo du!
|
... "this is a very l", 16) = 16
write(1, "this is a very l", 16this is a very l) = 16
read(3, "ong text!!!!!\n", 16) = 14
write(1, "ong text!!!!!\n", 14ong text!!!!!
) = 14
read(3,
(Needs two iterations for a very long text) |
this is a very long text!!!!!
|
... "", 16) = 0
close(3) = 0
|
^D
|