14 - Into to Networking
Class: CSCE-313
Notes:
3rd midterm on Friday 4/24 or Mon 4/27
Try to work out problems under Weekly-HW
- Doing this will help you understand the material better
What is a network?
Notes:
- Every device that you will probably ever used is at the edge of the network, you are always connecting at the edge
- You are connecting from something called an Access Point, that is then connected to the network
- If you connect a Cat6 cable to you PC, you are connecting from the edge
- Something inside is able to make a connection from you from whenever you are in the entire planet
- We are just interested in the API at the end devices, we are interested on that software that enables us to connect to the internet
The network does the routing
Notes:
- The only thing you know is how to reach your default gateway (the first hope device in the network that knows a lot more about the network than you do)
- Lets say you want to get to google.com, you create a packet and just send it to your gateway, it will receive it, parse it and route to wherever you are directing to.
- For every packet you have to read it from your NIC into your memory, parse it...
- The gateway decides on which direction to go, it does some hash or search in order to figure out on which direction to send it
The Internet: a "nuts and bolts" view
...
Notes:
- Every blue region is a network
- You may be in your home and all the devices in your home may be connected to an access point
- Traffic from your phone is going from devices to your router to your local ISP (optimum, etc.) - they server either your local area or some region
- There is this notion of an Autonomous system in the internet: it is an independently managed network
- They own certain set of pre-fixes and advertise them, when you want to reach a destination, you basically route it to the autonomous system
- It is actually pretty fragmented for a lot of reasons
- Billions of connected devices
- Switches route at layer 2
- Routers route at layer 3
"Fun" Internet-connected devices
...
Notes:
- They all want to be first-class citizens at the edge
- They are truly first-class entities in the network, but unfortunately they cannot always can be due to addressing limitations
The functionality of "networking"
....
Notes:
- One of the functionalities of the network API is the ability to name devices at the edge
- The way you communicate with someone is that you construct a packet, you put your destinations 32-bit number, you put your own 32-bit number as the source and you forward it to the network so that it gets routed to your destination.
- The cloud in the middle does the route for you, you just need to name an endpoint
- Modern networking is packet switched rather than connection-based
- Split conversation into little discrete packets, each of these packets has a destination and source IP
- We are individually routing each of these packets
- every individual packet is routed independently
- they do not necessarily need to take the same path on the network
- These packets can arrive out of order
- The third packet comes first, then the first, then the second for example
- The endpoint needs to do something in order to assemble the plackets in order
- It also can happen that a packet gets duplicated
- Every node in the middle will receive the packet, search for its destination and forward to the next node in the network.
- We need to have some convoluted logic in order to figure out reassembly of packages and re-fragmenting, removing duplicates
- But all of this is being done for you and its done at the edge!
- There is a notion of connection
- The sender and the receiver sort of agree that they are going to exchange messages, but before starting to send messages they need to set up a connection
- Is not like once you reach the end of some counter you have to break the connection
- The throughput in the network can suddenly change if network gets congested
- The endpoints can figure this out and slow down the transmission rate
- How this happens is also something that your networking stack is able to figure out
- There are other signals to figure out that something bad is happening in the network
Routing
...
Packet forwarding
...
Notes:
- Lets say you want to go from San Jose to Northampton
- If you could give the exact destination address of Northampton then that is fantastic
- But every node needs to know the exact destination
- You need to compress all the addresses into one city
- You can coalesced further and say you want to get first to a city closer to it
- Given an IP address, it will make the prefix smaller and smaller on each pass
- Once you get to the owner of that prefix, then the owner can route you to the destination
- Your packet has a destination, the local guy is able to look at your destination IP and say "go here", the vector is referred to direction, and distance refers to how far.
- All that routers do is to say: "Out of my n interfaces, This packet should go out on this interface"
Examples:
┌──(macc㉿kaliLab)-[~]
└─$ ifconfig -a
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.64.2 netmask 255.255.255.0 broadcast 192.168.64.255
inet6 fd15:7568:1b93:9ef1:49a9:ac71:34f7:cb32 prefixlen 64 scopeid 0x0<global>
inet6 fe80::60cf:81ff:fe55:308d prefixlen 64 scopeid 0x20<link>
inet6 fd15:7568:1b93:9ef1:60cf:81ff:fe55:308d prefixlen 64 scopeid 0x0<global>
ether 62:cf:81:55:30:8d txqueuelen 1000 (Ethernet)
RX packets 129735 bytes 97878313 (93.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 111498 bytes 19126431 (18.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 3450 bytes 13001871 (12.3 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3450 bytes 13001871 (12.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1500
inet 10.10.14.2 netmask 255.255.254.0 destination 10.10.14.2
inet6 fe80::8af5:89d2:6df1:a2d0 prefixlen 64 scopeid 0x20<link>
inet6 dead:beef:2::1000 prefixlen 64 scopeid 0x0<global>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500(UNSPEC)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 20 bytes 2821 (2.7 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- The IP address of my VM is
192.168.64.2
Protocol Layering
...
Notes:
- You are independent of what is at layer l - 1, l - 2 and so on.
- You can write you layer M by using functionality entirely at layer M - 1
- When you connect via
sshto your VM, every keystroke that you type can be converted to a packet that gets send to your VM- Your
sshclient is at layer 5 (application layer) - On layer 4 there will be a header encapsulating the your message with metadata of whatever the functionality of layer 4
- Layer 3 will do the same, at a header to the encapsulated message from layer 4 and encapsulate it again
- Layer 3 worries about what is going to happen if a frame is fragmented in the middle of the network, how it can be reconstructed, it also needs to put destination on source IP headers and so on.
- The layer 2 further adds its header and so on
- Your
- All of this layer is happening so that this guy uses its functionality of the previous layer and so on.
- Every character you type is potentially going through a different route that the endpoint has to later reassemble
The open system interconnection (OSI) model
...
Notes:
- In the US, they do not split them into exactly 7 layers, the last 3 layers are consolidated into the Application layer so that the application decides what to do exactly.
- You assume that any package you send will get to the other end
- There is a notion of session in protocols like HTTPS
- You can make a connection, come back, and 5 seconds later you do session resumption
- IT is very expensive to do cryptography so you set up your keys once, and then when you come back you resume your session.
The TCP/IP Reference Model
...
Notes:
- They do not have separate layers, you still need to do those, but it is the application that takes care of them
A client-server transaction
....
Notes:
- Here you have a client that makes a request to the server, and the server first gets the request, parses the request, and does what it needs to do
What's a protocol?
...
Notes
- In order to communicate effectively we need an understanding between the client and the server
- Alice makes a request
- Bob replies
Example of a client-server protocol:
curl
- Allows you to make HTTP request
- The server will read the request and serve the request
Example
┌──(macc㉿kaliLab)-[~]
└─$ curl -v https://www.google.com
- name resolves into addresses
- When you want to covert this name into an IP address, you will get a bunch of them
- Google will rotate these addresses, so if you make multiple requests it will go to different sites hosting the same, that is how load balancing works.
Here is the request that was send:
* Connected to www.google.com (142.251.151.119) port 443
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://www.google.com/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: www.google.com]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.15.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: www.google.com
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
Response looks like:
< HTTP/2 200
< date: Mon, 06 Apr 2026 19:36:58 GMT
< expires: -1
< cache-control: private, max-age=0
< content-type: text/html; charset=ISO-8859-1
< content-security-policy-report-only:
...
IP datagram
...
Notes:
- Think of the Internet as one big homogenous cloud
- It is nothing like this but you can assume so for now
- You are at the edge of this cloud
- We are only interested from going from one edge, somehow through this fabric, to another edge.
- Remember IP is implemented at layer 3.
- What your stack is doing is to discretize into little packets, they go into a network pipe, as these packets reach the other end, something on the other end is fixing the sequence.
- Every packet is at the IP layer
- IP header:
- It has a source ip address (32 bits)
- It has a destination ip address (32 bits)
- DNS is what translates human readable names to addresses.
- Encapsulated within L3 is L4
- Inside an IP packet there is a TCP packet
TCP header
...
Notes:
- If you are going to http you will store 80 on
dst port - If you are going to https you will store 443 on
dst port, and so on. - It does checksums, reliability using forward sequence numbers and so on.
A programmer's view of the Internet
...
Notes:
- For each of your interfaces you will get an IP address
Example:
> nslookup www.cs.tamu.edu
Server: 128.194.254.1
Address: 128.194.254.1#53
www.cs.tamu.edu canonical name = redirect.engr.tamu.edu.
redirect.engr.tamu.edu canonical name = d3s3b8hbw2bor0.cloudfront.net.
Name: d3s3b8hbw2bor0.cloudfront.net
Address: 3.169.221.28
Name: d3s3b8hbw2bor0.cloudfront.net
Address: 3.169.221.94
Name: d3s3b8hbw2bor0.cloudfront.net
Address: 3.169.221.95
Name: d3s3b8hbw2bor0.cloudfront.net
Address: 3.169.221.22
- It corresponds to a machine somewhere sitting in TAMU
- As it turns out, it has 4 different IP addresses that you can reach out
> dig +short www.google.com
142.251.152.119
142.251.153.119
142.251.154.119
142.251.155.119
142.251.156.119
142.251.157.119
142.251.150.119
142.251.151.119
- When you reach to google.com in your browser you are picking one of these!
- Note if you do it again, the order of the entries would change, this is because of the load balancing made by google.
IP Addresses
...
Notes:
- We will only look at IPv4 in this class
- IP addresses are packed in this struct:
struct in_addr { in_addr_t s_addr; }- This is just a 32-bit struct that serves as a wrapper to tell that this value is of type Internet Address.
Byte order for shorts and ints
...
Notes:
- This example illustrates endianness of network architecture
- Number is just a hex value (i.e. 0x01020304)
- If you are reading this number like that you are inherently assuming endianness, but different architectures do different things
- We have these two big forms:
- Little endian
- Big endian
- Code:
- You will do the assignment, then print the first 4 bytes
- A function called
htonlmeans: host to network long - Once we have turn
ato this "network long" we do this again
Result:
Host BO: 4 3 2 1
Network BO: 1 2 3 4
inet_ntop: 1.2.3.4.
- Note Mac is is little endian so the first sequence appears from the least significant byte to the most significant byte.
- The network does this differently, it is big endian.
- The receiver must know what is the byte order of the source ip address and the byte order of the destination ip address so it can decide the appropriate way to pack the bytes.
Dotted Decimal Notation
...
Notes:
- Here we have this utility function:
inet_ntop(network to presentation)- Will produce a nicely formatted string, which will take the first byte, second byte and so on. (this is for 32 bits addresses only)
Internet domain names
...
Notes:
- It is a distributed database, which means that not everything in the DNS is in one box or one clustered box, it is all over the internet.
- Below it are Top Level Domains (TLDs)
- .net, .edu, .goc, .com
- You then look at name like
tamuin.eduin order to get.tamu.edu.- Some server at TAMU manages this name server for the entire sub-space (it is hosted by a single organization)
- this entity owns that namespace
- There is a lot of complexity in the DNS, but the only thing we need to know is that it is distributed, not one entity owns the entirety of the DNS namespace.
Querying DNS
...
Notes:
- You can use the
digcommand to requests DNS lookups - When you try to resolve a name to an IP address, you are looking for its A record.
- There are different records for DNS
Example:
> dig linux2.cse.tamu.edu
; <<>> DiG 9.10.6 <<>> linux2.cse.tamu.edu
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53704
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 3, ADDITIONAL: 5
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1220
;; QUESTION SECTION:
;linux2.cse.tamu.edu. IN A
;; ANSWER SECTION:
linux2.cse.tamu.edu. 3600 IN A 128.194.166.90
;; AUTHORITY SECTION:
cse.tamu.edu. 3600 IN NS csce-info-grid.net.tamu.edu.
cse.tamu.edu. 3600 IN NS wemr-info-dhcp.net.tamu.edu.
cse.tamu.edu. 3600 IN NS csce-info-dhcp.net.tamu.edu.
;; ADDITIONAL SECTION:
wemr-info-dhcp.net.tamu.edu. 3600 IN A 128.194.211.237
csce-info-grid.net.tamu.edu. 3600 IN A 165.91.16.132
csce-info-dhcp.net.tamu.edu. 3600 IN A 128.194.169.147
csce-info-dhcp.net.tamu.edu. 3600 IN A 165.91.16.135
;; Query time: 12 msec
;; SERVER: 128.194.254.1#53(128.194.254.1)
;; WHEN: Wed Apr 08 14:21:12 CDT 2026
;; MSG SIZE rcvd: 227
- Cashing happens, and it is how we can control how frequent we want to respond
getaddrinfo - name -> ip mapping
...
Notes:
- First argument is the name you are trying to resolve
- The second argument is the name of the service, but we can leave it NULL.
hintssay what type of address you are trying to resolveaddrinfo- I want to resolve this name, but I want to resolve it in this address family
- You get back a linked list of this structure that tells the name resolves to many different IP addresses.
Example:
// Get a list of addrinfo recors
memset (&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET; // IPv4 only
hints.ai_socktype = SOCK_STREAM; // Connections only
if ((rc = getaddrinfo(host, NULL, &hints, &lisp)) != 0) {
fprintf(stderr, "getaddrinfo error")
ecit(1);
}
// Walk your rc linked list
getaddrinfo
...
Example:
- Basically this is the call
- Figuring out the why of the arguments might by difficult
Domain Naming System
...
Notes:
- You get back a linked list of
addrinfo(), but we are only interested in the address. - What we are going to do is to cast the pointer to
sockaddr
sockaddr = socket address
...
Notes:
- What are only interested in
struct in_addr sin_addr;(32 bit IP).
HW1 Q1 - Networking
Problem 1
- Explain the difference between host byte order and network byte order. Why is this distinction important in socket programming?
- Little endian and Big endian
- Why is this distinction? We have to agree on a common format, when the receiver gets a bitstream, it can figure out where the address start and where they end, but it needs to know in what order to interpret them. The people who wrote the standard picked big endian.
- Consider a 32-bit integer with the value 0x12345678 on a little-endian machine. What is this value when the bytes are interpreted as if in network byte order? Which function would you use to convert it, and what is the function signature?
- In big endian it would be: 0x78563412
- Presentation will give you a byte stream
- If you wanted to store the TCP port number 8080 in a socket address structure for network transmission, how would you prepare it? Show the code using the appropriate byte-order conversion function.
- You are going to do
host to network short
- You are going to do
- True or False: You need to convert the IP address returned by inet_pton() to network byte order before placing it in a socket address structure. Explain your answer.
Try all of these questions!
Anatomy of an internet connection
/CSCE-313/Lecture/Visual%20Aids/image-49.png)
Notes:
- Your client is using a port number
- Services are identified by a port number.
- When the server gets the connection, it can say "who is my peer?", where is the connection coming from?
- The client has an IP address and a port number, the way we specify services in our API is by using a 16-bit port number.
- On the client side it is randomly generated
- But on the server side, it has to be at a well known port, so that the client can specify it and reach it.
If you look at /etc/services you will see that http is defined as 80/tcp:
cat /etc/services | more
...
http 80/udp www www-http # World Wide Web HTTP
http 80/tcp www www-http # World Wide Web HTTP
...
- When a client makes a connection to a service it is identified by a port number, the network API is such that if you require a port number, your kernel will give you a random port number.
- The client could also be multi-home (have multiple network interface cards), if your connection is going out of an specific interface, your socket's IP address will get bound to that specific interface IP address.
- What we care about is that a connection has the following
- Client IP and client port
- Server IP and server port
- On the server side you could have many different services running, which you can identify by the port number!
Using Ports to Identify Services
/CSCE-313/Lecture/Visual%20Aids/image-50.png)
Notes:
- This is actually at layer 4 of your TCP/IP stack
- Layer 4 worries about demarking incoming packets to the correct port
- Remember that every packet has a layer 4 header embedded in a layer 3 header
- The kernel will basically send all packets which have a destination of port 80, to the service that is running in port 80.
- From the client host to the server host, there is an IP connection (a layer 3 connection).
Servers
Servers are long-running processes (daemons)
- Created at boot-time (typically) by the init process (process 1)
- Run continuously until the machine is turned off
Each server waits for requests to arrive on a well-known port associated with a particular service
- Port 23: telnet server
- Port 25: mail server
- Port 80: HTTP server
A machine that runs a server process is also often referred to as a "server"
Notes:
- There used to be a special process that creates all of your services
- It is no different than you starting them, but is convenient because it is guaranteed to start at boot time
- Regular user space process that is going to come up and configure itself.
Server examples
Web server (port 80)
- Resource: file serv/compute (CGI programs)
- Service: retrieves files and runs CGI programs on behalf of the client
FTP server (20, 21)
- Resource: files
- Service: stores and retrieve files
Telnet server (23)
- Resource: terminal
- Service: proxies a terminal on the server machine
Mail server (25)
- Resource: email "spool" file
- Service: stores mail messages in spool file
Notes: See /etc/services for a comprehensive list
of the services available on a UNIX machine
Notes:
- This is basically where the symbolic name of a service is mapped to a port number
- By convention we have already a lot of pre-defined port numbers: Port Numbers Cheat Sheet
Organization of an internet application
/CSCE-313/Lecture/Visual%20Aids/image-51.png)
Notes:
- You are living in the client application layer, and you are talking to a server which is also a user space program running at the application layer
- You are going to basically implement your client and server by making use of this socket API
- You do various things as a result of invoking the API in the kernel
- As you read or write on a socket, then data is sent or received through the network link
- Every packet is independently routed to its destination, and depending of the various fields of the header, it nows where to direct (which service to feed).
Network Programming with Sockets
- Sockets API
- An interface to the transport layer
- Introduced in 1981 by BSD 4.1
- Implemented as library and/or system calls
- An interface to the transport layer
Might see BSD Sockets: A Quick And Dirty Primer
Notes:
- This was done by one guy, a grad student at UC Berkley, way back in the early 80s
- It is the Application Interface of layer 4!
Stream sockets
/CSCE-313/Lecture/Visual%20Aids/image-52.png)
-
"This is long"
Notes:
- There are many kinds of protocols (i.e. tcp/udp)
- But the cross-protocol types are mostly uniform
- You somehow get a socket, on that socket, you send a byte stream (you can also do write), and you somehow are connected to the destination.
- What you expect is that the same byte sequence would appear on the other end, but notice that between the sender and the receiver is a big homorphous cloud, it is possible that your first uplink cannot send a long message, so you are force to break this first uplink into other packets, this is where fragmentation happens (breaking up a long message into several smaller messages)
- What your tcp will try to do is to fragment into smaller packets so that they do not get further fragmented in other steps
- Then you frame each one of those pieces into a packet, adn send those packets across (they can still get further fragmented)
- They get correctly assembled at the destination, and finally do a receive on the socket (essentially a read)
- You can get short reads, which are generally very likely, even though you ask for a lot of bytes, you may get only a few sent by the source.
Binding a socket?
- Each wall represents a NIC (local IP)
- Each socket represents a port
- Binding
plugging into a chosen (IP, port)
Notes:
- Socket: some kernel data structure that is an abstraction for a networking endpoint in the kernel
- You need to bind this socket to an end point
- We want to bind it to "this IP address" and "this port number"
- You have 16-bit port space
- Assigning a socket to an endpoint is called binding.
A Server-Client interaction in TCP - POSIX functions
/CSCE-313/Lecture/Visual%20Aids/image-53.png)
Notes:
- This is the one thing to remember in TCP/IP networking!
- The client and the server are asymmetrical, the server needs to comes up first before a client can connect to it
- Server
- The way a server comes up is that it creates a socket, once you have this free hanging socket, it needs to be binded to a specific address and port number
- At this point you have taken over this port number and associated to an IP address
- If you are a multi-home host, you want to bring up a service, you first create a socket, then you bind it first to a particular interface, and then to a particular port
- Most often you will bind to
0.0.0.0(any interface), but you could also specify an ISP or something, then nobody from other network interface will be able to connect to it.
- Most often you will bind to
- Then the server puts this socket into passive mode, in this passive mode it can accept connections
- Then it specifies to "make me a queue of n long" (i.e. up to 5 outstanding connections) - 5 clients possible, we do this by calling
listen(). - Have up to 5 guys to wait.
- Then it specifies to "make me a queue of n long" (i.e. up to 5 outstanding connections) - 5 clients possible, we do this by calling
- Then you accept the connection using
accept()- at this point the connection is either waiting, or connected
- Returning from
accpet()will provide a new socket, that socket will directly connect you to. - This is the socket that will give you direct connection to the client!
- Every time a new connection is formed you get a new socket.
- Now you have a bi-directional stream between the client and the server
- Note the client only has one socket.
- The way a server comes up is that it creates a socket, once you have this free hanging socket, it needs to be binded to a specific address and port number
- Client
- The client creates a socket and just connects to it.
- It specifies the server's IP address and port number
- When the connect returns successfully, that socket connects to the socket that was return by the
accept()on the server
- The server can do send and receive (read and write), and you can also do send and receive (read and write)
- These have added functionality like sending messages out-of-bound, but otherwise they work basically the same
- The client creates a socket and just connects to it.
Accepting a new connection
/CSCE-313/Lecture/Visual%20Aids/image-54.png)
Notes:
- A new connection arrives
- Your switchboard operator is basically going to connect the incoming connection to you but the operator first calls you: "are you ready to accept this connection"
- You get another phone and you are now get connected to a copy of your phone
- Every time a connection is made you have a new phone which connects to the call
Echo Server: accepet illustrates
/CSCE-313/Lecture/Visual%20Aids/image-55.png)
Notes:
- Usually the kernel picks a random port number for the client
- The connection is made, when this new connection is made, the server gets a socket, and the passive socket remains free for accepting more connections.
Function: socket
int socket(int family, int type, int protocol)
- Create a socket.
- Returns file descriptor or -1. Also sets
errnoon failure. family: address family (namespace)- AF_INET for IPv4
type: style of communication- SOCK_STREAM for TCP (with AF_INET)
protocol: protocol within type- typically 0
- Returns file descriptor or -1. Also sets
Notes:
- When we create a socket we specify an address family, this is saying what type of addresses the socket is made for
- For us the only thing we are interested in is IPv4
- The type is basically saying a style of communication
- TCP/UDP, etc.
- You can leave the
protocolto be 0, and the API will pick the communication type for you - Now we have a socket, but this socket is free floating, it is useless right now, it is just some data structure in the kernel
Example: socket
int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd */
struct sockaddr_in my_addr; /* my address */
struct sockaddr_in their_addr; /* connector addr */
int sin_size;
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
Notes:
- The way that a socket is exposed to you in your program is as a file descriptor
- You can basically make it look like a file (doing read and writes on it), and then you can do more advanced stuff like sends and receives.
Function: bind
int bind(int sockfd, sockaddr* myaddr, int addrlen)
- Bind a socket to a local IP address and port number
- Returns 0 on success, -1 and sets errno on failure
sockfd: socket file descriptor (returned from socket)myaddr: includes IP address and port number- IP address: INADDR_ANY ⇒ all IP addrs
- port number: set by kernel if 0 , else set by caller
addrlen: length of address structure= sizeof(struct sockaddr_in)
Notes:
- For us the socktype of
sockaddris the one for IPv4 - This family is basically the same as the address family of the socket
- We create a structure of type
sockadr_in, and just cast that tosockaddr - The
intis just saying how big of a data - When bind returns, your socket is now bound to an IP address and port number
- If you specify
INADR_ANY, you allow connections coming from every interface in your server infrastructure.
Function: listen
Put it in passive mode
int listen(int sockfd, int backlog)
- Put socket into passive state-wait for connections rather than initiate a connection
- Returns 0 on success, -1 and sets
errnoon failure sockfd: socket file descriptor (returned fromsocket)backlog: bound on length of un"accept"ed connection queue (connection backlog);- kernel will cap, thus better to set high
- Returns 0 on success, -1 and sets
Example:
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
Notes:
- If you expect a lot of connections, you want those connections to hang for the server to be able to serve when it comes available
- With listen you also put the socket in passive mode
Function: accept
int accept(int sockfd, sockaddr* cliaddr, int* addrlen);
- Block waiting for a new connection
- Returns file descriptor or -1 and sets
errnoon failure sockfd: socket file descriptor (returned fromsocket)cliaddr: IP address and port number of client (returned from call)addrlen: length of address structure = pointer tointset tosizeof(struct sockaddr_in)
- Returns file descriptor or -1 and sets
addrlenis a value-result argument- the caller passes the size of the address structure, the kernel returns the size of the client's address (the number of bytes written)
Notes:
- Give me the IP and port number of the client
- For us we are only interested with IPv4, so
sockaddrwill only besockaddr_in
Function: connect
int connect (int sockfd, sockaddr* servaddr, int addrlen)
- Connect to another socket.
- Returns 0 on success, -1 and sets
errnoon failure sockfd: socket file descriptor (returned fromsocket)servaddr: IP address and port number of serveraddrlen: length of address structure= sizeof (struct sockaddr_in)
- Returns 0 on success, -1 and sets
Notes:
- This is what the client uses to connect to the server
- If your connect returns successfully, then this file descriptor is now connected to the server, and now you can do read and write
Example server code (tcp-echo-server)
/CSCE-313/Lecture/Visual%20Aids/image-56.png)
Notes:
- First creates a socket -> gets TCP socket
- Specifies address family (i.e. IPv4) ==
AF_INET? - For us it is basically
SOCK_STREAM(which means tcp), and the 0 means that we are using the default implementation for that type of communication
- Specifies address family (i.e. IPv4) ==
- Then it binds the socket to your local endpoint
- We are binding it to all/any our network interfaces
- As a result you get a file descriptor in your file descriptor table
- Then the server puts the socket into passive mode with
listen()- In this example, the 129th connection will be dropped
- Then it
accepts()a connection and gets a client file descriptor- "Give me the address of the client that is connecting to me"
- You can now parse this
socketaddrand figure out the connection - You get a new descriptor in your file descriptor table that is connected directly to the client.
- Then we can normally use this file descriptor to read and write to!
- receive is basically like read and send is basically write and you can use all 4 of them to write to socket file descriptors.
- Test it using
telnet(a client)telnet localhost 9999
Example client code (tcp-client)
/CSCE-313/Lecture/Visual%20Aids/image-57.png)
Notes:
- What the client does is:
- Creates a socket, but does not bind it to an end point, it just does a
connect- Connect this socket to this remote address
- Backend the host and the port (convert to ip with
inet_addr) - Once it returns we can read and write from the socket
TCP Connection Example
/CSCE-313/Lecture/Visual%20Aids/image-58.png)
Notes:
- You have a 32-bit sequence number space
- When a client wants to connect to a server, it picks a random number in this space
- When it sends the connection formation protocol, it basically says: I am going to start sending you data that comes from r1
- By lookin gat the number that the server receives, it can tell if packets are lost
- The next packet should be r1 + 51, but these set of bytes are missing
- And now it can tell the client to send these bytes again
- The server keeps track of all the bytes that have been received from r1, and finds holes
- This is called reliability
- You need reliability in both directions, so the server now does the same and picks a random number r2
- Says: I am going to start sending you data marked at this offset
- Now the client will be able to tell if it does not received a sequence of bytes
- It is asymmetrical, the server side comes up first, then after
listen, the connection can arrive- When accepting, we will have the details of the connection.
Example: written
/CSCE-313/Lecture/Visual%20Aids/image-59.png)
/* Write "n" bytes to a descriptor */
ssize_t writen(int fd, const void *ptr, size_t n) {
size_t nleft;
ssize_t nwritten;
nleft = n;
while (nleft > 0) {
if ((nwritten = write(fd, ptr, nleft)) < 0) {
if (nleft == n)
return(-1); /* error, return -1 */
else
break; /* error, return amount written so far */
}
else if(nwritten == 0)
break;
nleft -= nwritten;
ptr += nwritten;
}
return(n - nleft); /* return >= 0 */
}
Notes:
- You basically set the number of bytes left to be
n, and now while the number of bytes left is grater than 0, you are going to try and write intofd- This is because we may have short writes
- If the write fails, you return from this function
- If you were able to write even 1 bytes to the socket, then you return the number of bytes that you were able to write.
- The important thing is that you are in a while loop so you keep trying until you fail
Example: readn
/CSCE-313/Lecture/Visual%20Aids/image-60.png)
/* Read "n" bytes from a descriptor */
ssize_t readn(int fd, void *ptr, size_t n) {
size_t nleft;
ssize_t nread;
nleft = n;
while (nleft > 0) {
if ((nread = read(fd, ptr, nleft)) < 0) {
if (nleft == n)
return(-1); /* error, return -1 */
else
break; /* error, return amt read */
}
else if(nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return(n - nleft); /* return >= 0 */
}
Notes:
- It will return the number of bytes actually read
- The number of bytes that you still have to read is reduced by 1
Server: `setsockopt()
The socket can be given some attributes
...
/* Eliminates "Address already in use" error from bind(). */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *) &optval , sizeof optval) == -1)
return -1;
Handy trick that allows us to rerun the server immediately after we kill it
- Otherwise, we would have to wait about 15 secs
- Eliminates "Address already in use" error from bind ()
Strongly suggest you do this for all your servers to simplify debugging
Notes:
- Sometimes you cannot bind to the same endpoint very quickly becuase there may be some packets interferring from your previous connection
- To get around this, then you do not have to wait before you can successfully bind