What is Socket Programming in C?

Learn via video course
FREE
View all courses
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
Topics Covered

Socket Programming is a method to connect two nodes over a network to establish a means of communication between those two nodes. A node represents a computer or a physical device with an internet connection. A socket is the endpoint used for connecting to a node. The signals required to implement the connection between two nodes are sent and received using the sockets on each node respectively.

State Diagram for Server and Client Model

We can understand the role of sockets in establishing a connection between two nodes over a network with the help of the following diagram,

SOCKET PROGRAMMING

  • The nodes are divided into two types, server node and client node.
  • The client node sends the connection signal and the server node receives the connection signal sent by the client node.
  • The connection between a server and client node is established using the socket over the transport layer of the internet.
  • After a connection has been established, the client and server nodes can share information between them using the read and write commands.
  • After sharing of information is done, the nodes terminate the connection.

We will look deeply at how the above process can be performed using socket programming in C in the following sections.

Stages for Server

Different stages must be performed on the server node to receive a connection sent by the client node. These stages are discussed elaborately in this section.

A. Socket Creation

The first stage deals with the creation of a socket, which is the basic component for sending or receiving signals between nodes. The sys/socket.h header has the necessary functions to create a socket in C. In socket programming in C, a socket can be created by the socket() function with syntax,

  • The domain represents the address family over which the communication will be performed. The domain is pre-fixed values present in the sys/socket.h header. Some domains are,
    • AF_LOCAL or AF_UNIX is used for local communication or in the case where the client and server are on the same node. These sockets are called UNIX domain sockets.
    • AF_INET is used to represent the IPv4 address of the client to which a connection should be made. Similarly AF_INET6 is used for IPv6 addresses. These sockets are called internet domain sockets.
    • AF_BLUETOOTH is used for low-level Bluetooth connection.
  • The type represents the type of communication used in the socket. Some mostly used types of communication are,
    • SOCK_STREAM uses the TCP(Transmission Control Protocol) to establish a connection. This type provides a reliable byte stream of data flow and is a connection-based protocol. These sockets are called stream sockets.
    • SOCK_DGRAM uses the UDP(User Datagram Protocol) which is unreliable and a connectionless protocol. These sockets are also called datagram sockets.
  • The protocol represents the protocol used in the socket. This is represented by a number. When there is only one protocol in the protocol family, the protocol number will be 0, or else the specific number for the protocol has to be specified.

The socket() function creates a socket and returns a file descriptor which represents an open file that will be utilized by the socket in reading and writing operations and the file descriptor is used to represent the socket in later stages. In case of an error in creating the socket, -1 is returned by the socket() function.

B. Setsockopt

The setsockopt() function in socket programming in C is used to specify some options for the socket to control the behavior of the socket. The syntax is,

  • The socket is the file descriptor returned by the socket() function.
  • The level parameter represents the level at which the option for the socket must be applied. The SOL_SOCKET represents the socket level and IPPROTO_TCP represents the TCP level.
  • The option_name specifies the rules or options that should be modified for the socket. Some useful options are,
    • SO_DEBUG is used to enable the recording of debugging information.
    • SO_REUSEADDR is used to enable the reusing of local addresses in the bind() function.
    • SO_SNDBUF is used to set the maximum buffer size that can be sent using the socket connection.
  • The option_value is used to specify the value for the options set in the option_name parameter.
  • The option_length is the length of the variable used to set the option value.

The function returns a value of 0 of data type int on the successful application of the option and a value of -1 on failure.

C. Bind

The bind() function in socket programming in C is used to assign an address to a socket created using the socket() function. The syntax of bind() function is,

  • The socket_descriptor is the value of the file descriptor returned by the socket() function.
  • The address is a structure of type sockaddr. We usually use a structure of type sockaddr_in to represent this information, because information such as port and address can only be stored in this structure. The sockaddr_in is cast to the sockaddr data type when calling the bind() function.
  • The length_of_address represents the size of the address passed as the second parameter.

The function returns 0 on binding the address and port successfully or returns -1 on failure.

D. Listen

The listen() function in socket programming is used to make the server node wait and listen for connections from the client node on the port and address specified by the bind() function. The syntax is,

  • The socket_descriptor represents the value of the file descriptor returned by the socket() function.
  • The back_log marks the maximum number of connection requests that can be made to the server by client nodes at a time. The number of requests made after the number specified by back_log may cause an error or will be ignored by the server if the options for retransmission are set.

The function returns 0 on listening on the address and port specified or returns -1 on failure.

E. Accept

The accept() function is used to establish a connection between the server and the client nodes for the transfer of data. The syntax is,

  • The socket_descriptor represents the value of the file descriptor returned by the socket() function.
  • The address is the variable of the sockaddr_in structure in which the address of the socket returned from the function will be stored.
  • The length_of_address depicts the size of the address parameter.

The accept() function creates a new socket from the first connection request for the specified socket_descriptor and returns the file descriptor of the new socket. The file descriptor of this new socket is used in the read() and write() functions to send and receive data to and from the client node.

Stages for Client

The client-side sends the connection requests to the server-side. To perform these several stages have to be performed on the client side,

A. Socket Connection

Similar to the server-side, the client-side also needs to create a socket using the socket() function and bind the socket to an address using the bind() function. This will create a socket that can send the connection request to the server.

B. Connect

The connect() function is used to send the connection request and connect to the server node. The syntax of the function is,

  • The socket_descriptor represents the value of the file descriptor returned by the socket() function during the creation of a socket on the client-side.
  • The address represents the structure with the information of the address and port number of the server node to which the connection is to be made.
  • The length_of_address is the size of the address structure used in the second parameter.

The connect() function returns a value of 0 on successfully connecting with the server and returns a value of -1 on error or the connection fails.

Implementation

Let us see the implementation of socket programming using the C programming language.

Server.c

In the server node, a socket must be created using the socket() function, the options for the socket are set using the setsockopt() function, and the socket is bound to an address and port using the bind() function, the socket is made to listen on the bound port and address using the listen() function and the connection request from the client is accepted using the accept() function. The main feature of server-side code is to prepare the node to listen for connection requests from the client node and establish a connection with the client node. The code used to implement the server node is,

In the above example, a socket is created and made ready to listen for connection signals from the client.

  • The socket uses the Ipv4 address family and is of type SOCK_STREAM which indicates the use of Transmission Control protocol.
  • The option SO_REUSEADDR is specified in the arguments. This option is a boolean option and the option_value of 1 depicts that this option is turned on.
  • The sockaddr_in structure has four data elements to represent the address family, port, internet address, and an additional space that is used to match the size of the sockaddr structure when performing casting operation. The structure of sockaddr_in is given below,

The structure in_addr present inside the sockaddr_in structure is,

A data element inside the structure can be accessed by the . operator and values are assigned to the elements.

  • The port number is passed to the htons() function which converts the port number stored in memory to network byte order.

  • The INADDR_ANY represents that any address can be used for binding. It generally indicates the address of 0.0.0.0. Other than INADDR_ANY, some useful addresses are,

    • INADDR_LOOPBACK which refers to the localhost of the node. The address is 127.0.0.1.
    • INADDR_BROADCAST is similar to INADDR_ANY but has the address 255.255.255.255. It is used for broadcast communication.
  • The struct sockaddr_in structure is cast to type struct sockaddr to match the syntax of the function. The sizeof() function is used to find the size of struct sockaddr.

  • The listen() function puts the socket in a listening state and a back_log of 4 states that a maximum of 4 connection requests can be made at a time to the server.

  • The accept() function establishes a connection between server and client and returns a new file descriptor.

  • The read() and write() functions are used to send and receive between client and server. The syntax of read() function is,

The data of specified size is read and stored in the buffer. The syntax of the write function is,

The data of specified size is written from the buffer. On successful read or write, the read() and write() functions return the number of bytes of data that has been read or written or return the value of -1 on failure.

  • The close() function is used to terminate the socket connection.

A network byte order is an order in which the most significant bits are stored first.

client.c

On the client-side, a socket is created by the socket() function and bound to a port and address using the bind() function. The client can send a connection request to the server node using the connect() function. The client-side code features sending a connection request to the server node. The code used to implement the client node is,

The creation of the socket is similar to the server-side and the server and client node are connected using the connect() function. Then the message is sent to the client using the write() function and messages can be received using the read() function.

Compiling

In Linux systems, we can use vim as a code editor. The following command is used to create and open a file using vim editor,

After the editor has opened, press i to enable insert mode and then press Ctrl+Shift+V to paste the code copied from client.c in the above sections. After pasting the code, press Esc and then type :wq to save the changes and quit the vim editor. Follow a similar procedure for server.c. In windows, we can simply use notepad or any other editor to perform the same.

The server code must be compiled and run before the client-side code to establish a connection.

The following command is used to compile the server code and save the compiled file as server_node,

The following command is used to compile the client code and save the compiled file as client_node,

Then the server_node and client_node files can be run on different terminals to see the output The following commands are used to run the compiled files,

In a separate terminal run the client_node,

The output on the client side is,

The output on the server side is,

Conclusion

  • Socket programming in C is used to create a connection between two nodes to share data over the internet.
  • The server node features listening for a connection signal and establishes a connection between the server and client node.
  • The client features sending of connection requests to the server.
  • There are different modes and options available to establish a connection between the client and server node.
  • A socket bound with a port and address is used for sending and receiving the data between client and server nodes.
  • The write() and read() functions are used to send and receive data through the sockets.