L14: Sockets Flashcards
Server View:
Basics
- Servers listen for an upcoming connection
- Respond when one is made
- Usually programmed to never exit
- Frequently called “daemons”
- Server listens for an incoming connection on a particular port #
- Upon connection, server process forks, creating a child process to respond to the client while the parent continues listening
Server View:
Port Number Ranges (2)
- Preassigned Ports
- Ports 0 - 1023
- Require root privilege to listen to
- Ephemeral Ports
- Ports > 1023
- Mostly not preassigned
Client View:
Basics
- Clients actively make a connection to a server
- Client selects:
- An host internet Address (xxx.xxx.xxx.xxx)
- A port number
- The client then attempts to connect to that host using that port number
- If the connection succeeds, it proceeds to read & write data through it’s connection
- Uses Either TCP or UDP
Client-Server:
Protocols Generally Used
between a Client and a Server
TCP
UDP
Server Side:
Programming Synopsis
- Make a socket using socket()
- Bind socket to a port using bind() to give it an “address”
- Call listen() to establish our process as a server
- Wait for a completed connection to be established with accept()
- Once a connection is accepted, fork()
- Parent closes the child’s socket, loops back to wait for another connection
- At some point, parent should use waitpid() to prevent zombie processes from accumulating
Child Process:
- Services the client connection and eventually exits
Important Libraries
for
Socket Programming
sys/types
sys/socket
netinet/in
arpa/inet
netdb
Important Types:
sock_addr_in
Structure that holds data associated with an internet address
- length
- AF_INET
- port number
- IP address
Operations:
Make a Socket
int listen_fd;
listen_fd = socket( AF_INET, SOCK_STREAM, 0)
AF_INET is the domain for the internet
SOCK_STREAM defines the protocol family (TCP)
If the result is negative, an error occured,
use perror to print message
Operations:
Bind a Socket to a Port
- Assume a socket was already created and passed to listen_fd
- Create a sock_addr_in structure, called servAddr
- Need to allocate memory with memset()
- Use the bind() function:
bind( listen_fd,
(struct sockaddr*) &servAddr,
sizeof(servAddr) );
Operation:
Listen and Accept Connections
listen( listen_fd, 1); //sets up connection queue 1 level deep
int connect_fd;
int length = sizeof( struct sock_addr_in);
struct sock_addr_in clientAddr;
connect_fd = accept( listen_fd,
(struct sock_addr*)&clientAddr,
&length);
- Waits(blocks) until a new connection established by the client
- Then, new descriptor for connection is returned (error < 0)
- Client’s address is written into the sock_addr structure
Operation:
Get a Text Host Name
struct hostent* hostEntry;
char* hostName;
hostEntry = gethostbyaddr( &(clientAddr.sin_addr),
sizeof( struct in_addr),
AF_INET);
hostName = hostEntry->h_name;
- Uses DNS to convert a numerical Internet Address to Host Name
- Returns NULL if error, use herror() to print error message
Operation:
Making a Connection
from a Client
int socket_fd;
socket_fd = socket( AF_INET, SOCK_STREAM, 0);
Make an internet socket using TCP Protocol
Same as server code.
Operation:
Set up Address of Server
(Basic Idea)
- Plug in the family and port number
- Get the numeric form of the server address
- Copy it into the address structure
Operation:
Connect to the Server
connect( socket_fd,
(struct sockAddr*)&servAddr,
sizeof(servAddr));
- A connection is established
- After which, I/O may be performed on socket_fd
- Sort of Equivalent to “open()” in File I/O
- Error indicated by returning negative number
Socket I/O
Major Points
- Use Unix read() and write()
- Similar to pipe I/O, but socket descriptors are bidirectional
- Always test for errors on reads or writes
- Use the descriptor for the connected socket in the same manner as for file I/O
EXCEPT:
- Read operations may return less than requested
- Less bytes does NOT indicate the last block of data, as it would for a local file
- Continue reading until no more bytes are read. This implies EOF