C Socket Programming
Needed Includes
-
<stdio.h>: Contains declarations for most I/O andprintf()andscanf()are a part of this. -
<sys/types.h>: Contains definitions of a number of data types. -
<sys/socket.h>: Contains socket-related definitions, e.g.sockaddr,bind(),listen(),accept() -
<netin/in.h>: Contains constants and structures needed for internet-related domain addresses, e.g.sockaddr_in -
<stdlib.h>: Defines variables and macros for performing general functions.-
Example:
int atoi(const char* str)which converts a string (ascii const char *) to int.
-
Socket Client-Server Model
From the above link:
The BSD server creates a socket, uses
bindto attach that socket to a port, and configures it as a listening socket. This allows the server to receive incoming connection requests. Afterwards,acceptis called, which will block the socket, until an incoming connection request is received. Whenacceptreturns, theSOCKADDRstructure will have been filled out with the originating IP Address and port of the incoming connection. Then,acceptcreates a new socket, which is then used to receive data until the connection is closed by the other side.
Server Setup
socket() creates an endpoint for communication and returns a file
descriptor that refers to that endpoint. The file descriptor
returned by a successful call will be the lowest-numbered file
descriptor not currently open for the process.
-
domain: The domain argument specifies a communication domain; this selects the protocol family which will be used for communication.-
Here we’ll be using
AF_INET, which is the IPv4 Internet protocol.
-
-
type: Specifies the communication semantics.-
Here we’ll be using
SOCK_STREAMfor a TCP stream.
-
-
protocol: specifies a particular protocol to be used with the socket. Normally only a single protocol exists to support a particular socket type within a given protocol family, in which case protocol can be specified as0.-
Here we’ll be using
0.
-
When a socket is created with socket(), it exists in a name
space (address family) but has no address assigned to it. bind()
assigns the address specified by addr to the socket referred to
by the file descriptor sockfd. addrlen specifies the size, in
bytes, of the address structure pointed to by addr.
Traditionally, this operation is called "assigning a name to a
socket".
Describes an IPv4 Internet domain socket address. The
sin_port and sin_addr members are stored in network byte
order.
struct sockaddr_in {
sa_family_t sin_family; /* AF_INET */
in_port_t sin_port; /* Port number */
struct in_addr sin_addr; /* IPv4 address */
};
See more information about sockaddr_in and in_addr here:
https://www.gta.ufrj.br/ensino/eel878/sockets/sockaddr_inman.html
listen() marks the socket referred to by sockfd as a passive
socket, that is, as a socket that will be used to accept incoming
connection requests using accept(2).
The accept() system call is used with connection-based socket
types (SOCK_STREAM, SOCK_SEQPACKET). It extracts the first
connection request on the queue of pending connections for the
listening socket, sockfd, creates a new connected socket, and
returns a new file descriptor referring to that socket. The
newly created socket is not in the listening state. The original
socket sockfd is unaffected by this call.
read() attempts to read up to count bytes from file descriptor fd
into the buffer starting at buf.
Server Teardown
Finally, we’ll need to clean up any file descriptors we opened for sockets.
close() closes a file descriptor, so that it no longer refers to
any file and may be reused. Any record locks (see
fcntl(2)) held
on the file it was associated with, and owned by the process, are
removed (regardless of the file descriptor that was used to
obtain the lock).
Client Setup
Given node and service, which identify an Internet host and a
service, getaddrinfo() returns one or more addrinfo structures,
each of which contains an Internet address that can be specified
in a call to bind(2)
or connect(2).
The getaddrinfo() function combines the functionality provided by the
gethostbyname(3)
and getservbyname(3)
functions into a single interface, but unlike the latter functions,
getaddrinfo() is reentrant and allows programs to eliminate
IPv4-versus-IPv6 dependencies.
int getaddrinfo(const char *restrict node,
const char *restrict service,
const struct addrinfo *restrict hints,
struct addrinfo **restrict res);
This function converts the network address structure src in the
af address family into a character string. The resulting string
is copied to the buffer pointed to by dst, which must be a non-
null pointer. The caller specifies the number of bytes available
in this buffer in the argument size.