Socket Programming
Socket Programming
network. It allows for the exchange of data between devices by establishing a connection through
a socket, which is a software endpoint that facilitates sending and receiving data.
1. Socket:
2. Types of Sockets:
Stream Sockets (TCP): This type of socket uses the Transmission Control Protocol
(TCP) for communication. It ensures reliable, ordered, and error-checked delivery of
data. TCP is connection-based.
Datagram Sockets (UDP): This type of socket uses the User Datagram Protocol (UDP)
for communication. It is connectionless, meaning there is no need to establish a
connection before sending data. It does not guarantee delivery, order, or error checking,
but it is faster than TCP.
Server-side: The server creates a socket and listens for incoming connections from
clients. Once a client connects, the server accepts the connection and communicates with
the client.
Client-side: The client creates a socket and connects to the server using the server's IP
address and port number. Once the connection is established, data can be sent and
received.
Server Code:
python
Copy code
import socket
try:
print("Connection established with", client_address)
finally:
connection.close()
Client Code:
python
Copy code
import socket
Web Servers and Clients: HTTP servers use sockets to communicate with clients (web
browsers).
File Transfer: Protocols like FTP use sockets to transfer files.
Chat Applications: Real-time messaging applications use sockets to send and receive
messages.
Remote Access: Secure Shell (SSH) and Remote Desktop use sockets for remote control
of systems.
Here’s a basic example of a GET request made by the client to initiate the
opening handshake:
GET wss://example.com:8181/ HTTP/1.1
Host: localhost: 8181
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: zy6Dy9mSAIM7GJZNf9rI1A==
The server must return an HTTP 101 Switching Protocols response code for the
WebSocket connection to be successfully established:
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Sec-WebSocket-Accept: EDJa7WCAQQzMCYNJM42Syuo9SqQ=
Upgrade: websocket
Opening handshake headers
The table below describes the headers used by the client and the server
during the opening handshake - both the required ones (illustrated in the
code snippets above) and the optional ones.
Require
Header Description
d
Host Yes The host name and optionally the port number of the
server to which the request is being sent.
Connection Yes Indicates that the client wants to negotiate a change
in the way the connection is being used. Value must
be Upgrade .
It’s worth mentioning a few more details about two of the required headers
used during the WebSocket handshake: Sec-WebSocket-Key and Sec-WebSocket-
Accept . Together, these headers are essential in guaranteeing that both the
server and the client are capable of communicating over WebSockets.
After a successful opening handshake, the client and the server can use the
WebSocket connection to exchange messages in full-duplex mode. A
WebSocket message consists of one or more frames.
The WebSocket frame has a binary syntax and contains several pieces of
information, as shown in the following figure:
RSV 1-3
RSV1 , RSV2 ,
and RSV3 are reserved bits. They must be 0 unless
an extension was negotiated during the opening handshake that defines
non-zero values.
Opcodes
Every frame has an opcode that determines how to interpret that frame’s
payload data. The standard opcodes currently in use are defined by RFC
6455 and maintained by the Internet Assigned Numbers Authority (IANA).
Opcod
Description
e
0 Continuation frame; continues the payload from the previous frame.
1 Indicates a text frame (UTF-8 text data).
2 Indicates a binary frame.
3-7 Reserved for custom data frames.
8 Connection close frame; leads to the connection being terminated.
9 A ping frame. Serves as a heartbeat mechanism ensuring the
connection is still alive. The receiver must respond with a pong
frame.
10 A pong frame. Serves as a heartbeat mechanism ensuring the
connection is still alive. Sent as a response after receiving a ping
frame.
11-15 Reserved for custom control frames.
Masking
Each WebSocket frame sent by the client to the server needs to be masked
with the help of a random masking-key (32-bit value). This key is contained
within the frame, and it’s used to obfuscate the payload data. However,
when data flows the other way around, the server must not mask any frames
it sends to the client.
The WebSocket protocol encodes the length of the payload data using a
variable number of bytes:
For payloads <126 bytes, the length is packed into the first two frame
header bytes.
For payloads of 126 bytes, two extra header bytes are used to indicate
length.
If the payload is 127 bytes, eight additional header bytes are used to
indicate its length.
The WebSocket protocol supports two types of payload data: text (UTF-8
Unicode text) and binary.
The standard status codes that can be used during the closing handshake
are defined by RFC 6455, and listed in the following table:
Status
Name Description
code
0-999 N/A Codes below 1000 are invalid and cannot be used.
1000 Normal Indicates a normal closure, meaning that the purpose
closure for which the WebSocket connection was established
has been fulfilled.
1001 Going away Should be used when closing the connection and there
is no expectation that a follow-up connection will be
attempted (e.g., server shutting down, or browser
navigating away from the page).
1002 Protocol The endpoint is terminating the connection due to a
error protocol error.
1003 Unsupported The connection is being terminated because the
data endpoint received data of a type it cannot handle (e.g.,
a text-only endpoint receiving binary data).
1004 Reserved Reserved. A meaning might be defined in the future.
1005 No status Used by apps and the WebSocket API to indicate that
received no status code was received, although one was
expected.
1006 Abnormal Used by apps and the WebSocket API to indicate that a
closure connection was closed abnormally (e.g., without
sending or receiving a close frame).
1007 Invalid The endpoint is terminating the connection because it
payload data received a message containing inconsistent data (e.g.,
non-UTF-8 data within a text message).
1008 Policy The endpoint is terminating the connection because it
violation received a message that violates its policy. This is a
generic status code; it should be used when other
status codes are not suitable, or if there is a need to
hide specific details about the policy.
1009 Message too The endpoint is terminating the connection due to
big receiving a data frame that is too large to process.
1010 Mandatory The client is terminating the connection because the
extension server failed to negotiate an extension during the
opening handshake.
1011 Internal error The server is terminating the connection because it
encountered an unexpected condition that prevented it
from fulfilling the request.
1012 Service The server is terminating the connection because it is
restart restarting.
1013 Try again The server is terminating the connection due to a
later temporary condition, e.g., it is overloaded.
1014 Bad gateway The server was acting as a gateway or proxy and
received an invalid response from the upstream server.
Similar to 502 Bad Gateway HTTP status code.
1015 TLS Reserved. Indicates that the connection was closed due
handshake to a failure to perform a TLS handshake (e.g., the
server certificate can’t be verified).
1016- N/A Reserved for future use by the WebSocket standard.
1999
2000- N/A Reserved for future use by WebSocket extensions.
2999
3000- N/A Reserved for use by libraries, frameworks, and
3999 applications. Available for registration at IANA on a
first-come, first-serve basis.
4000- N/A Range reserved for private use in applications.
4999
Both the client and the web server can initiate the closing handshake. Upon
receiving a close frame, an endpoint (client or server) has to send
a close frame as a response (echoing the status code received). After an
endpoint has both sent and received a close frame, the closing handshake is
complete, and the WebSocket connection is considered closed.
The close() method is used to close the WebSocket connection. After this
method is called, no more data can be sent or received over the WebSocket
connection.
While WebSockets have plenty of advantages, they also come with some
disadvantages. Here are the main ones:
WebSockets are not optimized for streaming audio and video data.
WebSockets don’t automatically recover when connections are
terminated.
Some environments (such as corporate networks with proxy servers)
will block WebSocket connections.
WebSockets are stateful, which makes them hard to use in large-scale
systems.
Learn more about the pros and cons of WebSockets
WebSocket is an excellent choice for use cases where it’s critical (or at least
desirable) for data to be sent and consumed in realtime or near-realtime.
However, there is rarely a one-size-fits-all protocol — different protocols
serve different purposes better than others. Realtime alternatives to
WebSockets include:
Server-Sent Events
HTTP long polling
MQTT
WebRTC
WebTransport
Learn more about WebSocket alternatives
How to start building realtime experiences with WebSockets
Getting started with WebSockets is straightforward. The WebSocket API is
trivial to use, and there are numerous WebSocket libraries and frameworks
available in every programming language. Most of them are built on top of
the raw WebSocket protocol, while providing additional capabilities — thus
making it easier and more convenient for developers to implement
WebSockets into their apps and build WebSocket-based functionality.
To provide a directly runnable bundle for the chat application, we can combine the backend and
frontend into a single project structure. Follow these steps:
Project Structure
plaintext
Copy code
real-time-chat/
│
├── backend/ # Backend (Node.js + Express + Socket.IO)
│ ├── server.js # Server code
│ └── package.json # Backend dependencies
│
├── frontend/ # Frontend (React)
│ ├── public/ # React public folder
│ ├── src/ # React source code
│ ├── package.json # Frontend dependencies
│ └── App.css # CSS for the React app
│
├── README.md # Instructions to run the app
└── start.sh # Script to start the full app
Bundle Preparation
1. Backend Code
File: backend/server.js
javascript
Copy code
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const cors = require('cors');
const path = require('path');
app.use(cors());
app.use(express.static(path.join(__dirname, '../frontend/build')));
socket.on('disconnect', () => {
console.log('A user disconnected:', socket.id);
});
});
File: backend/package.json
json
Copy code
{
"name": "backend",
"version": "1.0.0",
"main": "server.js",
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"socket.io": "^4.7.1"
},
"scripts": {
"start": "node server.js"
}
}
bash
Copy code
npm install
2. Frontend Code
File: frontend/src/App.js
javascript
Copy code
import React, { useState, useEffect } from 'react';
import { io } from 'socket.io-client';
import './App.css';
useEffect(() => {
socket.on('receiveMessage', (newMessage) => {
setMessages((prevMessages) => [...prevMessages, newMessage]);
});
return () => {
socket.off('receiveMessage');
};
}, []);
return (
<div className="app">
<h1>Real-Time Chat</h1>
<div className="chat-box">
{messages.map((msg, index) => (
<div key={index} className="message">
{msg}
</div>
))}
</div>
<div className="input-box">
<input
type="text"
placeholder="Type a message..."
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
<button onClick={sendMessage}>Send</button>
</div>
</div>
);
};
File: frontend/src/App.css
css
Copy code
body {
margin: 0;
font-family: Arial, sans-serif;
background-color: #f4f4f4;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.app {
background: #ffffff;
width: 400px;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
gap: 20px;
}
h1 {
text-align: center;
color: #333;
}
.chat-box {
height: 300px;
overflow-y: auto;
border: 1px solid #ccc;
border-radius: 5px;
padding: 10px;
background: #f9f9f9;
}
.message {
margin-bottom: 10px;
padding: 8px 12px;
background: #007bff;
color: white;
border-radius: 20px;
}
.input-box {
display: flex;
gap: 10px;
}
input {
flex: 1;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
button {
padding: 10px 20px;
background: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background: #0056b3;
}
File: frontend/package.json
json
Copy code
{
"name": "frontend",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"socket.io-client": "^4.7.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build"
}
}
bash
Copy code
npm install
npm run build
3. Startup Script
File: start.sh
bash
Copy code
#!/bin/bash
cd backend
npm start
bash
Copy code
chmod +x start.sh
bash
Copy code
./start.sh
You said:
you have forgotten that told you to explain the flow of code what will happen when user will
send request what part of client side code will run and what will happen in server how server
code each line will handle the request the exact working of the code
ChatGPT said:
ChatGPT
Sure! Let's go through the entire flow of the application step-by-step, explaining both the client-
side and server-side actions, including how the code handles requests and responses.
1. Application Initialization
Frontend
When the React app starts, the App component initializes the following:
o useState Hooks: To manage the message (current input) and messages (array of
all messages).
o useEffect Hook: Sets up a socket connection to the server and listens for
incoming messages ('receiveMessage' event). When a message is received, it
updates the messages array to display the message in the chatbox.
Backend
The backend Express server starts and serves two main roles:
1. Serves the built React frontend files to the client when they access the application
URL (http://localhost:5000).
2. Handles WebSocket connections via Socket.IO to facilitate real-time
communication between clients.
2. Sending a Message
When a user types a message and clicks Send, here's what happens:
Client-Side Flow
javascript
Copy code
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
/>
o The onChange event updates the message state with the user's input as they type.
2. Send Message Button (onClick)
javascript
Copy code
<button onClick={sendMessage}>Send</button>
javascript
Copy code
const sendMessage = () => {
if (message.trim()) {
socket.emit('sendMessage', message); // Send message to server
setMessage(''); // Clear the input box
}
};
javascript
Copy code
socket.on('sendMessage', (message) => {
io.emit('receiveMessage', message);
});
Client-Side Flow
javascript
Copy code
socket.on('receiveMessage', (newMessage) => {
setMessages((prevMessages) => [...prevMessages, newMessage]);
});
o The client listens for the 'receiveMessage' event emitted by the server.
o When a message is received, it updates the messages state using setMessages to
include the new message.
2. Rendering the Messages
javascript
Copy code
{messages.map((msg, index) => (
<div key={index} className="message">
{msg}
</div>
))}
o The messages array is mapped to render each message in the chatbox. The new
message appears instantly for all connected clients.
Frontend: App.js
Socket Initialization
javascript
Copy code
const socket = io();
javascript
Copy code
useEffect(() => {
socket.on('receiveMessage', (newMessage) => {
setMessages((prevMessages) => [...prevMessages, newMessage]);
});
return () => {
socket.off('receiveMessage');
};
}, []);
javascript
Copy code
const sendMessage = () => {
if (message.trim()) {
socket.emit('sendMessage', message);
setMessage('');
}
};
o Sends the current message to the server using socket.emit() and clears the
input field.
Backend: server.js
Express Initialization
javascript
Copy code
const app = express();
const server = http.createServer(app);
const io = new Server(server);
javascript
Copy code
app.use(express.static(path.join(__dirname, '../frontend/build')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../frontend/build/index.html'));
});
o Serves the React app's static files. This ensures the frontend is accessible when
you visit http://localhost:5000.
WebSocket Events
javascript
Copy code
io.on('connection', (socket) => {
console.log('A user connected:', socket.id);
socket.on('disconnect', () => {
console.log('A user disconnected:', socket.id);
});
});
The exact difference between the Socket API (WebSocket API) and Socket.IO lies in their
design, features, and functionality. Here’s a detailed comparison:
Protocol: WebSocket API is built on top of the WebSocket protocol (RFC 6455), which
provides full-duplex, bi-directional communication channels between the client (browser)
and the server. The connection is established over HTTP/HTTPS during the handshake
but is then upgraded to WebSocket for persistent communication.
Features:
o Low-level API: The WebSocket API is a simple, low-level API that is part of the
HTML5 specification for browser-based real-time communication.
o Connection-oriented: Once a WebSocket connection is established, the
connection remains open until either the client or the server closes it.
o No Automatic Reconnection: WebSocket API does not support automatic
reconnection or fallback mechanisms in case of connection issues. If the
connection drops, it needs to be manually re-established.
o No Built-in Message Broadcasting: WebSockets don't include built-in support
for broadcasting messages to multiple clients or managing rooms.
Use Case: WebSocket is useful when you need a simple, low-level, full-duplex
connection. It's perfect for real-time applications like chat apps, notifications, or live
updates where you just need to establish a connection and exchange data.
Protocol: Socket.IO is a library built on top of WebSockets and other protocols (like
HTTP long-polling) for real-time communication. It automatically negotiates and falls
back to the best protocol available based on the environment (WebSocket, long-polling,
etc.).
Features:
o High-level API: Socket.IO provides a high-level abstraction over WebSockets,
making it easier to implement real-time features such as broadcasting,
reconnection, and more.
o Automatic Reconnection: Socket.IO has built-in support for automatic
reconnection. If a connection drops, it will try to reconnect automatically without
any additional code from the developer.
o Rooms & Namespaces: Socket.IO allows grouping clients into "rooms" to
broadcast messages to specific clients or subsets of clients. It also supports
namespaces, which are separate channels for communication within the same
server instance.
o Event-based Communication: Socket.IO uses custom events to facilitate
communication, making it easier to structure real-time interactions.
o Fallback: If WebSocket is not supported or fails to connect (due to network
issues or firewalls), Socket.IO can automatically fall back to HTTP long-polling
or other protocols, ensuring reliability across different environments.
Use Case: Socket.IO is ideal for applications that require more advanced features like
automatic reconnection, broadcasting, handling disconnections, and grouping clients. It's
typically used for chat apps, live notifications, multiplayer games, real-time collaboration
tools, etc.
Socket.IO Methods:
Key Differences:
Summary:
The WebSocket API is a low-level standard API for establishing a persistent connection
between client and server for real-time communication.
Socket.IO is a high-level library built on top of WebSocket (and other fallback
protocols) that adds extra features like automatic reconnection, broadcasting, rooms, and
namespaces, making it more suitable for building complex real-time applications.
In simple terms:
Use WebSocket API if you need a simple and direct communication channel and can
handle disconnections and reconnections manually.
Use Socket.IO if you need more features like automatic reconnections, event-based
communication, broadcasting, and better handling of network failures.