TCP sockets

杨文联

<ol><li>What is a socket?</li><li>What is TCP?</li><li>Client-server Architecture.</li><li>Implementation</li><li>Further Reading</li><li>Summary</li></ol> 1 <p class="ql-block"><span style="font-size:15px;">A socket is a structure that allows communication between different processes on the same computer or different computers. A socket allows us to communicate by sending and receiving data over the network. In simple terms, it is a way for a computer to talk to other computers on the network.</span></p> 2 <p class="ql-block"><span style="font-size:15px;">TCP refers to the Transmission Control Protocol. It is one of the main protocol used for communication over the internet. Some of the features of this protocol are:</span></p><ul><li><span style="font-size:15px;">It is a connection-oriented communication protocol.</span></li><li><span style="font-size:15px;">It used three-way handshake to establish reliable connections.</span></li><li><span style="font-size:15px;">TCP gurantees the delivery of the data packets.</span></li></ul> 3 <p class="ql-block"><span style="font-size:15px;">A client-server architecture is a model in computer networking, where the server provides some service to the client. In this architecture, the client computer sends a request to the server computer through a network (internet). The server accepts this request and sends the required data to the client.</span></p><p class="ql-block"><span style="font-size:15px;">In simple terms, we can say</span></p><p class="ql-block"><span style="font-size:15px;">Server is a remote computer which provides some services.</span></p><p class="ql-block"><span style="font-size:15px;">Client is the one that request the server for these services.</span></p> <p class="ql-block"><span style="font-size:15px;">The server-side process can be broken down into the following steps:</span></p><p class="ql-block"><span style="font-size:15px;">socket() – create TCP socket.</span></p><p class="ql-block"><span style="font-size:15px;">bind() – bind the TCP socket to the server address (ip and port).</span></p><p class="ql-block"><span style="font-size:15px;">listen() – waiting for the clients.</span></p><p class="ql-block"><span style="font-size:15px;">accept() – connection is established between the client and server.</span></p><p class="ql-block"><span style="font-size:15px;">recv() and send () – communicate with each other.</span></p><p class="ql-block"><span style="font-size:15px;">close() – close the connection from the client.</span></p> <p class="ql-block"><span style="font-size:15px;">The client-side process can be broken down into the following steps:</span></p><p class="ql-block"><span style="font-size:15px;">socket() – create TCP socket.</span></p><p class="ql-block"><span style="font-size:15px;">connect() – connect to the server.</span></p><p class="ql-block"><span style="font-size:15px;">recv() and send () – communicate with each other.</span></p><p class="ql-block"><span style="font-size:15px;">close() – close the connection.</span></p><p class="ql-block"><span style="font-size:15px;">We begin by including all the required header files, defining the IP (Internet Protocol) address and the port number. We also define the required variable used later in this program.</span></p> <p class="ql-block"><span style="font-size:15px;">Here is an example of a simple TCP client-server communication code in C for Linux:</span></p><p class="ql-block"><span style="font-size:15px;">Client side code (tcp_client.c):</span></p><p class="ql-block"><span style="font-size:15px;">```c</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;stdio.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;stdlib.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;string.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;sys/socket.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;netinet/in.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;arpa/inet.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#define PORT 12345</span></p><p class="ql-block"><span style="font-size:15px;">int main() {</span></p><p class="ql-block"><span style="font-size:15px;"> int client_socket;</span></p><p class="ql-block"><span style="font-size:15px;"> struct sockaddr_in server_addr;</span></p><p class="ql-block"><span style="font-size:15px;"> char message[100];</span></p><p class="ql-block"><span style="font-size:15px;"> client_socket = socket(AF_INET, SOCK_STREAM, 0 </span></p><p class="ql-block"><span style="font-size:15px;"> if (_socket &lt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("socket creation failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> memset(&server_addr, '0', sizeof(server_addr));</span></p><p class="ql-block"><span style="font-size:15px;"> </span></p><p class="ql-block"><span style="font-size:15px;"> server_addr.sin_family = AF_INET;</span></p><p class="ql-block"><span style="font-size:15px;"> server_addr.sin_port = htons(PORT);</span></p><p class="ql-block"><span style="font-size:15px;"> if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) &lt;= 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("Invalid address/ Address not supported");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) &lt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("Connection failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> strcpy(message, "Hello, server!");</span></p><p class="ql-block"><span style="font-size:15px;"> send(client_socket, message, strlen(message), 0);</span></p><p class="ql-block"><span style="font-size:15px;"> close(client_socket);</span></p><p class="ql-block"><span style="font-size:15px;"> return 0;</span></p><p class="ql-block"><span style="font-size:15px;">}</span></p><p class="ql-block"><span style="font-size:15px;">```</span></p><p class="ql-block"><span style="font-size:15px;">Server side code (tcp_server.c):</span></p><p class="ql-block"><span style="font-size:15px;">```c</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;stdio.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;stdlib.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;string.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;sys/socket.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;netinet/in.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#define PORT 12345</span></p><p class="ql-block"><span style="font-size:15px;">int main() {</span></p><p class="ql-block"><span style="font-size:15px;"> int server_socket, client_socket;</span></p><p class="ql-block"><span style="font-size:15px;"> struct sockaddr_in server_addr, client_addr;</span></p><p class="ql-block"><span style="font-size:15px;"> char message[100];</span></p><p class="ql-block"><span style="font-size:15px;"> server_socket = socket(AF_INET, SOCK_STREAM, 0);</span></p><p class="ql-block"><span style="font-size:15px;"> if (server_socket &lt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("socket creation failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> memset(&server_addr, '0', sizeof(server_addr));</span></p><p class="ql-block"><span style="font-size:15px;"> server_addr.sin_family = AF_INET;</span></p><p class="ql-block"><span style="font-size:15px;"> server_addr.sin_addr.s_addr = htonl(INADDR_ANY);</span></p><p class="ql-block"><span style="font-size:15px;"> server_addr.sin_port = htons(PORT);</span></p><p class="ql-block"><span style="font-size:15px;"> if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) &lt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("bind failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> if (listen(server_socket, 5) &lt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("listen failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> client_socket = accept(server_socket, (struct sockaddr *)&client_addr, (socklen_t*)&client_addr);</span></p><p class="ql-block"><span style="font-size:15px;"> </span></p><p class="ql-block"><span style="font-size:15px;"> read(client_socket, message, sizeof(message));</span></p><p class="ql-block"><span style="font-size:15px;"> printf("Client message: %s\n", message);</span></p><p class="ql-block"><span style="font-size:15px;"> close(client_socket);</span></p><p class="ql-block"><span style="font-size:15px;"> close(server_socket);</span></p><p class="ql-block"><span style="font-size:15px;"> return 0;</span></p><p class="ql-block"><span style="font-size:15px;">}</span></p><p class="ql-block"><span style="font-size:15px;">```</span></p><p class="ql-block"><span style="font-size:15px;">These are basic examples to get you started with TCP client-server communication in C for Linux.</span></p> TCP server <p class="ql-block"><span style="font-size:15px;">#include &lt;stdio.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;stdlib.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;string.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;unistd.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;sys/types.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;sys/socket.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#include &lt;netinet/in.h&gt;</span></p><p class="ql-block"><span style="font-size:15px;">#define PORT 8888</span></p><p class="ql-block"><span style="font-size:15px;">#define MAX_CONNECTIONS 10</span></p><p class="ql-block"><span style="font-size:15px;">int main() {</span></p><p class="ql-block"><span style="font-size:15px;"> int server_fd, new_socket, valread;</span></p><p class="ql-block"><span style="font-size:15px;"> struct sockaddr_in address;</span></p><p class="ql-block"><span style="font-size:15px;"> int addrlen = sizeof(address);</span></p><p class="ql-block"><span style="font-size:15px;"> char buffer[1024] = {0};</span></p><p class="ql-block"><span style="font-size:15px;"> int client_sockets[MAX_CONNECTIONS] = {0};</span></p><p class="ql-block"><span style="font-size:15px;"> if ((server_fd = socket(AF_INET, </span></p><p class="ql-block"><span style="font-size:15px;"> SOCK_STREAM, 0)) == 0) </span></p><p class="ql-block"><span style="font-size:15px;"> {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("Socket creation failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> address.sin_family = AF_INET;</span></p><p class="ql-block"><span style="font-size:15px;"> address.sin_addr.s_addr = INADDR_ANY;</span></p><p class="ql-block"><span style="font-size:15px;"> address.sin_port = htons(PORT);</span></p><p class="ql-block"><span style="font-size:15px;"> if (bind(server_fd, (struct sockaddr *)&address, </span></p><p class="ql-block"><span style="font-size:15px;"> sizeof(address)) &lt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("Bind failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> if (listen(server_fd, MAX_CONNECTIONS) &lt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("Listen failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> fd_set readfds;</span></p><p class="ql-block"><span style="font-size:15px;"> while(1) {</span></p><p class="ql-block"><span style="font-size:15px;"> FD_ZERO(&readfds);</span></p><p class="ql-block"><span style="font-size:15px;"> FD_SET(server_fd, &readfds);</span></p><p class="ql-block"><span style="font-size:15px;"> for (int i = 0; i &lt; MAX_CONNECTIONS; i++) {</span></p><p class="ql-block"><span style="font-size:15px;"> if (client_sockets[i] &gt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> FD_SET(client_sockets[i], &readfds);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> if (select(FD_SETSIZE, &readfds, NULL, NULL, NULL) &lt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("Select failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> if (FD_ISSET(server_fd, &readfds)) {</span></p><p class="ql-block"><span style="font-size:15px;"> if ((new_socket = accept(server_fd, </span></p><p class="ql-block"><span style="font-size:15px;"> (struct sockaddr *)&address, </span></p><p class="ql-block"><span style="font-size:15px;">(socklen_t*)&addrlen)) &lt; 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> perror("Accept failed");</span></p><p class="ql-block"><span style="font-size:15px;"> exit(EXIT_FAILURE);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> for (int i = 0; i &lt; MAX_CONNECTIONS; i++) {</span></p><p class="ql-block"><span style="font-size:15px;"> if (client_sockets[i] == 0) {</span></p><p class="ql-block"><span style="font-size:15px;"> client_sockets[i] = new_socket;</span></p><p class="ql-block"><span style="font-size:15px;"> break;</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> for (int i = 0; i &lt; MAX_CONNECTIONS; i++) {</span></p><p class="ql-block"><span style="font-size:15px;"> if (FD_ISSET(client_sockets[i], &readfds)) {</span></p><p class="ql-block"><span style="font-size:15px;"> valread = read(client_sockets[i], buffer, 1024);</span></p><p class="ql-block"><span style="font-size:15px;"> printf("Client message: %s\n", buffer);</span></p><p class="ql-block"><span style="font-size:15px;"> char *response = "Message received";</span></p><p class="ql-block"><span style="font-size:15px;"> send(client_sockets[i], response, strlen(response), 0);</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> }</span></p><p class="ql-block"><span style="font-size:15px;"> return 0;</span></p><p class="ql-block"><span style="font-size:15px;">}</span></p>