Skip to content

TCP/IP

TCP/IP Socket Functions.

a socket interface as per the Open Group Base Specifications

Server Example

The following shows, how to create a socket, bind it to a specific address and port, accept connections, send and receive data.

It uses the socket related functions to demonstrate their use when implementing a server

c

#include "socket.h"
#include <stdio.h>
#include <string.h>

int main() {
    const char *addr = "<IPv4 address>"; // Replace with an IPv4 address
    in_port_t port = <port>; // Replace with a port number

    // Create a socket
    int s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (s < 0) {
        perror("Failed to create socket");
        return -1;
    }

    // Bind the socket to a specific address
    struct sockaddr_in name;
    name.sin_family = AF_INET;
    name.sin_port = htons(port);
    name.sin_addr.s_addr = inet_addr(addr);
    if (bind(s, (struct sockaddr *)&name, sizeof(name)) < 0) {
        perror("Failed to bind socket");
        return -1;
    }

    // Start listening on the socket
    if (listen(s, 1) < 0) {
        perror("Failed to listen on socket");
        return -1;
    }

    // Accept a connection
    struct sockaddr_storage their_addr;
    socklen_t size = sizeof(their_addr);
    int new_s = accept(s, (struct sockaddr *)&their_addr, &size);
    if (new_s < 0) {
        perror("Failed to accept connection");
        return -1;
    }

    // Send a message to the client
    const char *message = "Welcome! This is a test server.\n";
    if (send(new_s, message, strlen(message), 0) < 0) {
        perror("Failed to send message");
        return -1;
    }

    // Read a message from the client and print it
    char buffer[1024];
    int bytes_received = recv(new_s, buffer, sizeof(buffer) - 1, 0);
    if (bytes_received < 0) {
        perror("Failed to receive a message");
        return -1;
    }
    buffer[bytes_received] = '\0';
    printf("Received: %s\n", buffer);

    return 0;
}

Client Example

This example demonstrates the usage of socket(), connect(), send(), recv(), and close() functions to create a TCP client

The example creates the following steps:

  1. Create a socket using the socket function
  2. Connect to the server using the connect() function
  3. Send a message to the server using the send() function
  4. Receive a response from the server using the recv() function
  5. Close the socket
cpp
#include "socket.h"
#include <string.h>
#include <stdio.h>

void write_and_read_from_server() {
    // Create the socket
    int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock < 0) {
        perror("socket()");
        return;
    }

    // Define server information
    struct sockaddr_in server_info;
    server_info.sin_family = AF_INET;
    server_info.sin_port = htons(8000); // Change to your server's port
    server_info.sin_addr.s_addr = inet_addr("<your_server_ip_address>"); // Change to your server's IP

    // Connect to the server
    if (connect(sock, (struct sockaddr*)&server_info, sizeof(server_info)) < 0) {
        perror("connect()");
        return;
    }

    // Send a message to the server
    const char* message = "Hello, Server!";
    if (send(sock, message, strlen(message), 0) < 0) {
        perror("send()");
        return;
    }

    // Receive a response from the server
    char buffer[1024];
    int bytes_received = recv(sock, buffer, sizeof(buffer) - 1, 0);

    if (bytes_received < 0) {
        perror("recv()");
        return;
    }

    buffer[bytes_received] = '\0'; // Null-terminate the received data

    // Print the server's response
    printf("Received: %s\n", buffer);

    // Shutdown the socket
    shutdown(sock, SHUT_RDWR);
}

DNS Lookup Example

This example demonstrates the use of getaddrinfo and gethostbyname for DNS Resolution

cpp
#include <netdb.h>
#include <string.h> // For strcpy

void dnsResolveExample() {

    // Using getaddrinfo
     struct addrinfo hints;
     struct addrinfo *res;

     memset(&hints, 0, sizeof(hints));
     hints.ai_family = AF_INET; // Allow IPv4
     hints.ai_socktype = SOCK_STREAM; // TCP socket

     int status = getaddrinfo("your.domain.com", NULL, &hints, &res);
     if (status != 0) {
         printf("getaddrinfo error: %s\n", gai_strerror(status));
         return;
     }

     freeaddrinfo(res); // Free the linked list

      // Using gethostbyname
      struct hostent *he = gethostbyname("your.domain.com");
      if (he == NULL) {
         printf("gethostbyname error: %s\n", hstrerror(h_errno));
         return;
     }

     char ip[INET_ADDRSTRLEN];
     inet_ntop(he->h_addrtype, he->h_addr, ip, sizeof(ip));
     printf("IP:%s\n", ip);

 }

Types

Name
structhostent
structaddrinfo
structin_addr
The in_addr struct represents an IP address.
structsockaddr_in
IPv4 socket address structure.
structsockaddr
The sockaddr struct represents a generic socket address structure.
structsockaddr_storage
A generic structure to store socket address information.

Functions Overview

Name
struct hostent *gethostbyname(const char * name)
intgethostbyname_r(const char * name, struct hostent * ret, char * buf, size_t buflen, struct hostent ** result, int * h_errnop)
voidfreeaddrinfo(struct addrinfo * ai)
intgetaddrinfo(const char * nodename, const char * servname, const struct addrinfo * hints, struct addrinfo ** res)
intsocket(int domain, int type, int protocol)
Creates a new socket and returns its descriptor.
intconnect(int s, const struct sockaddr * name, socklen_t namelen)
Connects a socket to a remote address.
intbind(int s, const struct sockaddr * name, socklen_t namelen)
Binds a socket to a specific address and port.
intlisten(int s, int backlog)
Set a socket into listening mode.
intaccept(int s, struct sockaddr * addr, socklen_t * addrlen)
Accept a connection on a socket.
intrecv(int s, void * buf, size_t len, int flags)
Receive data from a socket.
intselect(int maxfdp1, fd_set * readset, fd_set * writeset, fd_set * exceptset, struct timeval * timeout)
Select function.
intsend(int s, const void * data, size_t size, int flags)
Sends data on a socket.
intshutdown(int s, int how)
Shutdown a socket connection.
ssize_tsendto(int s, const void * data, size_t size, int flags, const struct sockaddr * to, socklen_t tolen)
Sends data over a socket to a specified destination.
ssize_trecvfrom(int s, void * mem, size_t len, int flags, struct sockaddr * from, socklen_t * fromlen)
Receive data from a socket.
intfcntl(int s, int cmd, ... )
Controls file descriptor behavior.
intinet_pton(int af, const char * src, void * dst)
Converts a string representation of an IP address to a binary format.
const char *inet_ntop(int af, const void * src, char * dst, socklen_t size)
Converts a network address from binary to presentation format.
intsetsockopt(int socket, int level, int option_name, const void * option_value, socklen_t option_len)
Sets a socket option.
intgetsockopt(int s, int level, int optname, void * optval, socklen_t * optlen)
Retrieves options for the specified socket.
intgetsockname(int s, struct sockaddr * name, socklen_t * namelen)
Retrieves the local address of a socket.

Function Details

function gethostbyname

cpp
struct hostent * gethostbyname(
    const char * name
)

Parameters:

  • name the hostname to resolve

Return: entry containing one address of family AF_INET for the host with name name

Returns an entry containing IP addresses for a hostname. Due to internal limitations, only one address is returned.

function gethostbyname_r

cpp
int gethostbyname_r(
    const char * name,
    struct hostent * ret,
    char * buf,
    size_t buflen,
    struct hostent ** result,
    int * h_errnop
)

Parameters:

  • name the hostname to resolve
  • ret pre-allocated struct where to store the result
  • buf pre-allocated buffer where to store additional data
  • buflen the size of buf
  • result pointer to a hostent pointer that is set to ret on success and set to zero on error
  • h_errnop pointer to an int where to store errors (instead of modifying the global h_errno)

Return: 0 on success, non-zero on error, additional error information is stored in *h_errnop instead of h_errno to be thread-safe

Thread-safe variant of gethostbyname: instead of using a static buffer, this function takes buffer and errno pointers as arguments and uses these for the result.

function freeaddrinfo

cpp
void freeaddrinfo(
    struct addrinfo * ai
)

Parameters:

  • ai struct addrinfo to free

Frees one or more addrinfo structures returned by getaddrinfo(), along with any additional storage associated with those structures. If the ai_next field of the structure is not null, the entire list of structures is freed.

function getaddrinfo

cpp
int getaddrinfo(
    const char * nodename,
    const char * servname,
    const struct addrinfo * hints,
    struct addrinfo ** res
)

Parameters:

  • nodename descriptive name or address string of the host (may be NULL -> local address)
  • servname port number as string of NULL
  • hints structure containing input values that set socktype and protocol
  • res pointer to a pointer where to store the result (set to NULL on failure)

Return: 0 on success, non-zero on failure

Translates the name of a service location (for example, a host name) and/or a service name and returns a set of socket addresses and associated information to be used in creating a socket with which to address the specified service. Memory for the result is allocated internally and must be freed by calling freeaddrinfo()!

Due to internal limitations, only the first address of a host is returned. Also, service names are not supported (only port numbers)!

function socket

cpp
int socket(
    int domain,
    int type,
    int protocol
)

Creates a new socket and returns its descriptor.

Parameters:

  • domain The domain of the socket (e.g. PF_INET for IPv4).
  • type The type of the socket (e.g. SOCK_STREAM for TCP, SOCK_DGRAM for UDP).
  • protocol The protocol to be used by the socket (e.g. IPPROTO_UDP).

See: errno

Return: The socket descriptor if successful, otherwise -1.

Note: This function does not provide support for SOCK_SEQPACKET or SOCK_RAW socket types.

This function creates a new socket using the specified domain, type, and protocol. The socket descriptor is returned if the socket creation is successful, otherwise -1 is returned.

function connect

cpp
int connect(
    int s,
    const struct sockaddr * name,
    socklen_t namelen
)

Connects a socket to a remote address.

Parameters:

  • s The socket file descriptor.
  • name A pointer to the sockaddr structure containing the address to connect to.
  • namelen The length of the sockaddr structure.

Return: Returns 0 on success and -1 on error, setting errno.

This function establishes a connection between the socket referred to by the file descriptor s and the address specified by the structure pointed to by name.

function bind

cpp
int bind(
    int s,
    const struct sockaddr * name,
    socklen_t namelen
)

Binds a socket to a specific address and port.

Parameters:

  • s The socket descriptor.
  • name Pointer to a struct sockaddr containing the local address and port information.
  • namelen The length of the address structure pointed to by name.

Return: 0 on success, or -1 on error.

This function assigns a local address and port to a socket. The binding is used to determine the local interface and port to send and receive data through the socket.

function listen

cpp
int listen(
    int s,
    int backlog
)

Set a socket into listening mode.

Parameters:

  • s The socket to set to listening mode.
  • backlog The maximum number of pending connections that can be queued up.

Return: 0 on success, non-zero on failure.

Note: The number of connections that can be queued up is limited by the backlog parameter, which must not exceed the value of TCP_LISTEN_BACKLOG.

This function sets a socket into listening mode. The socket must not have been used for another connection previously.

function accept

cpp
int accept(
    int s,
    struct sockaddr * addr,
    socklen_t * addrlen
)

Accept a connection on a socket.

Parameters:

  • s The socket descriptor
  • addr Pointer to a sockaddr structure that will be filled with the source address and port of the incoming connection. Set to NULL if not needed.
  • addrlen Pointer to an integer variable that specifies the size of the sockaddr structure. Upon return, it will be updated with the actual size of the sockaddr structure. Set to NULL if not needed.

Return: On success, the new socket descriptor is returned. On error, -1 is returned and errno is set appropriately.

Note:

  • The new socket is independent of the listening socket, and can be used to communicate with the incoming client.
  • The newly created socket must be closed after use, using the close() function.
  • This function is blocking, and will wait until a new connection arrives.
  • If addr and addrlen are not NULL, the source address and port of the incoming connection will be filled in the sockaddr structure. The sa_family field of the sockaddr structure will be set to the address family of the incoming connection. If addr is NULL, the source address and port information will not be returned.
  • This function is thread-safe.

This function is used to accept a connection on a listening socket. It waits until a new connection arrives, and then creates a new socket for that connection.

function recv

cpp
int recv(
    int s,
    void * buf,
    size_t len,
    int flags
)

Receive data from a socket.

Parameters:

  • s Socket descriptor.
  • buf Pointer to the buffer to store the received data.
  • len Maximum length of the buffer.
  • flags Receive flags.

Return: On success, returns the number of bytes received. On failure, returns -1.

Note: This function is responsible for receiving data from a socket. The received data is stored in the provided buffer, up to the maximum length specified. The actual number of bytes received may be less than the maximum length, which can be checked using the return value. The flags parameter can be used to modify the behavior of the receive operation. The function accepts different flag options to control receive operations, such as OOB (Out of Band) and PEEK.

This function is used to receive data from a socket.

function select

cpp
int select(
    int maxfdp1,
    fd_set * readset,
    fd_set * writeset,
    fd_set * exceptset,
    struct timeval * timeout
)

Select function.

Parameters:

  • maxfdp1 The highest file descriptor value to be checked plus one.
  • readset Pointer to the set of file descriptors to be checked for readability.
  • writeset Pointer to the set of file descriptors to be checked for writability.
  • exceptset Pointer to the set of file descriptors to be checked for exceptional conditions.
  • timeout Pointer to a struct timeval specifying the maximum time to wait for an event to occur. If NULL, select will block until an event occurs.

Return: The total number of file descriptors ready and contained in the sets (i.e., the sum of the file descriptors in readset, writeset, and exceptset) if the return value is positive, or -1 on error. On error, the errno variable is set appropriately to indicate the cause of the error.

Note: The select function modifies all three descriptor sets passed as parameters.

The select function allows monitoring multiple file descriptors for readability, writability, or exceptional conditions. It is useful for multiplexing I/O operations and handling asynchronous events.

function send

cpp
int send(
    int s,
    const void * data,
    size_t size,
    int flags
)

Sends data on a socket.

Parameters:

  • s Socket descriptor of the socket to send data on.
  • data A pointer to the buffer containing the data to be sent.
  • size The length of the data in bytes.
  • flags Specifies the type of message transmission.

Return: Returns the number of bytes sent on success, or -1 on failure.

This function is used to send data on a socket.

function shutdown

cpp
int shutdown(
    int s,
    int how
)

Shutdown a socket connection.

Parameters:

  • s The socket descriptor to shutdown.

  • how Specifies the type of shutdown. It can have one of the following values:

  • SHUT_RD: Disables further receive operations.

  • SHUT_WR: Disables further send operations.

  • SHUT_RDWR: Disables further send and receive operations.

Return: 0 if successful, or -1 if an error occurred. The specific error code can be obtained by calling errno which evaluates to *cw_errno.

Note: The function shutdown can only be used with TCP sockets. If any other socket type is used, the function will return an error with errno set to EOPNOTSUPP.

This function closes one end of a full-duplex connection identified by the socket descriptor s. It allows either sending, receiving, or both to be shutdown. The how parameter determines which operation(s) to shutdown.

function sendto

cpp
ssize_t sendto(
    int s,
    const void * data,
    size_t size,
    int flags,
    const struct sockaddr * to,
    socklen_t tolen
)

Sends data over a socket to a specified destination.

Parameters:

  • s The socket descriptor.
  • data A pointer to the data that should be sent.
  • size The size of the data in bytes.
  • flags Flags to control the behavior of the function.
  • to A pointer to a sockaddr structure that contains the destination address.
  • tolen The size of the destination address structure.

Return: The number of bytes sent on success, or -1 on failure.

This function sends the specified data over the socket with the given descriptor to the specified destination address.

function recvfrom

cpp
ssize_t recvfrom(
    int s,
    void * mem,
    size_t len,
    int flags,
    struct sockaddr * from,
    socklen_t * fromlen
)

Receive data from a socket.

Parameters:

  • s The socket descriptor.
  • mem A pointer to the buffer where the received data will be stored.
  • len The maximum number of bytes to receive.
  • flags Specifies the type of message reception.
  • from A pointer to an address structure where the source address of the data will be stored.
  • fromlen Length of the address structure.

Return: On success, the number of bytes received is returned. On failure, -1 is returned. The errno variable is set to indicate the error.

The recvfrom function is used to receive data over a socket. It attempts to receive up to len bytes of data into the memory pointed to by mem.

function fcntl

cpp
int fcntl(
    int s,
    int cmd,
    ... 
)

Controls file descriptor behavior.

Parameters:

  • s The file descriptor.
  • cmd The command to perform.

Return: The result of the operation, or -1 in case of failure.

Note: The behavior of this function is platform-dependent.

The fcntl function performs various control operations on file descriptors.

function inet_pton

cpp
int inet_pton(
    int af,
    const char * src,
    void * dst
)

Converts a string representation of an IP address to a binary format.

Parameters:

  • af The address family of the IP address (AF_INET or AF_INET6).
  • src A pointer to the string containing the IP address in ASCII format.
  • dst A pointer to the buffer where the binary format of the IP address will be stored.

Return: 0 if the conversion is successful, or -1 if an error occurs.

Note: The dst buffer must be large enough to hold the binary format of the IP address. The size of the buffer depends on the address family. For IPv4 addresses, the dst must be at least the size of ip4_addr_t. For IPv6 addresses, the dst must be at least the size of ip6_addr_t.

This function converts a string representation of an IP address from the specified address family (AF_INET or AF_INET6) to its binary format.

This function supports both IPv4 and IPv6 addresses. For IPv4 addresses (AF_INET), it calls the function ip4addr_aton to convert the string to a binary format. For IPv6 addresses (AF_INET6), it first converts the string to a temporary ip6_addr_t variable using ip6addr_aton, and then memcpy's the address to the destination buffer if the conversion is successful. If an unsupported address family is specified, it sets the errno to EAFNOSUPPORT and returns -1.

function inet_ntop

cpp
const char * inet_ntop(
    int af,
    const void * src,
    char * dst,
    socklen_t size
)

Converts a network address from binary to presentation format.

Parameters:

  • af The address family (AF_INET or AF_INET6).
  • src Pointer to binary network address.
  • dst Pointer to buffer to store the resulting address string.
  • size The size of the dst buffer.

Return: Pointer to the resulting address string on success, or NULL on failure.

This function converts the network address given in the src buffer from binary format to a string in presentation format. The resulting address string is stored in the dst buffer.

The af parameter specifies the desired address family. It can be AF_INET for IPv4 or AF_INET6 for IPv6 addresses. The src parameter is a pointer to the network address in binary format. The dst parameter is a pointer to the buffer where the resulting address string will be stored. The size parameter specifies the size of the buffer pointed to by dst.

The function returns a pointer to the resulting address string if successful. However, if the size of the buffer pointed to by dst is smaller than the resulting address string, the function sets the errno variable to ENOSPC and returns NULL.

The function supports both IPv4 and IPv6 addresses. For IPv4 addresses use (af = AF_INET) to convert the address to a string format. For IPv6 addresses use (af = AF_INET6) to convert the address to a string format.

If the desired address family is not supported (af != AF_INET or af != AF_INET6), the function sets the errno variable to EAFNOSUPPORT.

function setsockopt

cpp
int setsockopt(
    int socket,
    int level,
    int option_name,
    const void * option_value,
    socklen_t option_len
)

Sets a socket option.

Parameters:

  • socket The socket descriptor.
  • level The level at which the option is defined (e.g. SOL_SOCKET).
  • option_name The option to set.
  • option_value A pointer to the option value.
  • option_len The length of the option value.

Return: 0 on success, -1 on failure.

Note: This function is an implementation of the lwIP setsockopt function. It is used to set socket options such as the debug level, buffer size, etc. The level and option_name parameters determine the specific option to set, and the option_value parameter points to the new value for that option. The option_len parameter specifies the length of the option value.

This function sets the value of a socket option for a given socket.

function getsockopt

cpp
int getsockopt(
    int s,
    int level,
    int optname,
    void * optval,
    socklen_t * optlen
)

Retrieves options for the specified socket.

Parameters:

  • s The socket for which to get the options.
  • level The level at which the option is defined.
  • optname The name of the option to get.
  • optval A pointer to the buffer to receive the option value.
  • optlen A pointer to the size of the buffer, and on return the size of the option value.

Return: 0 on success, -1 on failure.

Par: Related Definitions

  • #socklen_t: A typedef for the size of socket-related objects.

This function is used to get socket options at the specified level for the given socket.

function getsockname

cpp
int getsockname(
    int s,
    struct sockaddr * name,
    socklen_t * namelen
)

Retrieves the local address of a socket.

Parameters:

  • s The socket descriptor.
  • name A pointer to a sockaddr structure that will hold the local address information.
  • namelen A pointer to the length of the sockaddr structure. On input, it should contain the size of the buffer pointed to by name. On output, it will be set to the actual size of the local address returned.

See:

Return: On success, zero is returned. On error, -1 is returned and errno is set appropriately.

This function retrieves the local address associated with a socket. The local address is returned in the form of a sockaddr structure.