In order to establish a TCP connection, one party must send a SYN packet to the other, receive a SYN-ACK packet back, and finally send an ACK packet.
In this class, we focus on TCP. Where might UDP be used?
socket
creates an endpoint for communication and returns a file descriptor that refers to that endpoint.
bind
associates an abstract network socket created with socket
to an actual networking interface/address.
listen
marks a socket as “passive”, or ready to accept incoming connections.
accept
accepts an incoming connection on a socket that has been listening.
connect
is used to connect a socket to a given address (which might have a socket listening for connections).
Make sure to check errors for every call, networking can fail at any point! All networking functions specify in their manpages what types of errors you might have to deal with.
Make sure to set socket options to reuse to enable effective debugging of the server - otherwise, the system won’t immediately reallow you to use a socket once it’s been closed by your program.
Most server applications are interupted through a signal, but you shouldn’t do all of the cleanup in the signal handler because not every function is signal handler safe (think back to CS233 interrupts). This pattern avoids this issue:
int is_running = 1;
int handler(){
is_running = 0;
}
int main(){
while(is_running){ /*...*/};
close(...);
}
Try to modularize your functions so that everything is not in the main method. This is ideally because we need to tell the system that we are done using shared resources like sockets, and we need to determine when a socket goes “out of scope” – we don’t have RAII like in C++ so we have to determine that ourselves, and modularizing your code makes it easy to see when things are in/out of scope.