Example in python can be seen here: https://github.com/Descent098/ezcv-http/tree/main/socket%20testing
Uses ezcv to generate html and then sockets as the http server
Networking data is in big endian, meaning the integers in hex values go from left to right
So for example int x = 0xAABBCCDD
would be understood as AA, BB, CC, DD (where each 2 letters is a byte value)
In some host systems they operate using little endian meaning the order is reversed DD, CC, BB, AA and the values need to be reversed before being sent
The network sending format is called Network Byte Order (or big endian), and the host format is called Host Byte Order (can be big or little endian)
You can use the following functions to convert Host byte order to Network Byte order (big endian):
htons()
[for shorts], htonl()
[for longs]
to convert back use:
ntohs()
[for shorts], ntohl()
[for longs]
To format IP addresses:
ASCII dotted to binary: inet_aton()
Binary to ASCII dotted: inet_ntoa()
// This is a view of the structs that will be used later, they're included in the headerfiles
sockaddr{ // Can be used for any networking protocol
unsigned short sa_family; // The family of addresses the address belongs to (IPV4 [PF_INET], IPV6 etc.)
char sa_data[14]; // The IP address
}
sock_addr_in{ // Specifically used for internet
short sin_family; // The family of addresses the address belongs to (IPV4 [PF_INET], IPV6 etc.)
unsigned short sin_port; // Port number
struct in_addr sin_addr; // IP Address
char sin_zero[8]; // Pad
}
struct in_addr{
unsigned long s_addr; // 4 bytes long and represents an IP address
}
Call is used to create a socket. The socket is what is actually used to do all the network interactions and sends/receives to/from other endpoints.
domain
or family
; the type of communication, typically PF_INET
which corresponds to IPV4
type
; the type of socket, typically SOCK_STREAM
for TCP and SOCK_DGRAM
for UDP
protocol
or proto
; sometimes used with specific socket types, but almost always 0
int socket(int domain, int type, int protocol)
Returns a socket descriptor on it's success, and returns -1 when there's an error
socket(PF_INET, SOCK_STREAM, 0)
class socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None)
fileno
is just a way to specify a config file for a socket, if fileno
is specified, the values for family, type, and proto are auto-detected from the specified file descriptor.
import socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET == IPV4, SOCK_STREAM == TCP
The step in the process that actually attaches a socket to a specific port and IP address
int Bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen)
sockfd
is the socket descriptor returned by socket()
my_addr
= pointer to a valid sockaddr_in
struct cast as a sockaddr
pointer
addrlen
is the length of the sockarrd_in
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 8080
// Initialize socket
sock = socket(PF_INET, SOCK_STREAM, 0)
// Configure socket
struct sockaddr_in sock_config;
sock_config.sin_family = PF_INET; // IPV4 family address
sock_config.sin_port = htons(80); // port 80 or the common http port
sock_config.sin_addr.s_addr = INADDR_ANY;
bzero(&sock_config, 8);
// Bind socket
bind(sock, (struct sockaddr *)sock_config, sizeof(sock_config));
socket.bind(tuple[str,int])
socket.bind()
takes in a tuple of a string
and an int
, the string is the IP address (must be IPV4 in this case), and the integer is the port in (IP_ADDRESS, PORT)
order.
import socket
# Initialize socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET == IPV4, SOCK_STREAM == TCP
# Bind Socket
address = '127.0.0.1' # The IP address to bind to
port = 8080 # The port to bind to
server_socket.bind((address, port))
Tells the computer to wait for connections on the configured socket
int Listen(int sock, int backlog)
sock
is the socket returned by socket()
backlog
= maximum pending connections queue
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 8080
// Initialize socket
sock = socket(AF_INET, SOCK_STREAM, 0)
// Configure socket
struct sockaddr_in sock_config;
sock_config.sin_family = PF_INET; // IPV4 family address
sock_config.sin_port = htons(PORT); // port 8080 defined above
sock_config.sin_addr.s_addr = INADDR_ANY;
bzero(&sock_config, 8);
// Bind socket
bind(sock, (struct sockaddr *)sock_config, sizeof(sock_config));
// Listen for up to 10 connections
listen(sock, 10)
import socket
# Initialize socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET == IPV4, SOCK_STREAM == TCP
# Bind Socket
address = '127.0.0.1' # The IP address to bind to
port = 8080 # The port to bind to
server_socket.bind((address, port))
# Listen on socket for up to 10 conections
server_socket.listen(10)
Tells the computer to wait for connections on the configured socket
int Accept(int socket, (struct sockaddr *)&client, socklen_t *client_len)
socket
is the socket integer returned by socket()
client
is what will hold the new client's information when accept returns
client_len
is the pointer to the size of the client struct
// Setting up the Necessary Structs
sockaddr{ // Can be used for any networking protocol
unsigned short sa_family; // The family of addresses the address belongs to (IPV4 [PF_INET], IPV6 etc.)
char sa_data[14]; // The IP address
}
sock_addr_in{ // Specifically used for internet
short sin_family; // The family of addresses the address belongs to (IPV4 [PF_INET], IPV6 etc.)
unsigned short sin_port; // Port number
struct in_addr sin_addr; // IP Address
char sin_zero[8]; // Pad
}
struct in_addr{
unsigned long s_addr; // 4 bytes long and represents an IP address
}
// Initialize socket
sock = socket(PF_INET, SOCK_STREAM, 0)
// Configure socket
struct sockaddr_in sock_config;
sock_config.sin_family = PF_INET; // IPV4 family address
sock_config.sin_port = htons(80); // port 80 or the common http port
sock_config.sin_addr.s_addr = INADDR_ANY;
bzero(&sock_config, 8);
// Bind socket
bind(sock, (struct sockaddr *)sock_config, sizeof(sock_config));
// Listen for up to 10 connections
listen(sock, 10)
// Accepting new connections
struct sockaddr_in client;
int len = sizeof(client);
Accept(sock, (struct sockaddr *)&client, &len);
import socket
# Initialize socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET == IPV4, SOCK_STREAM == TCP
# Bind Socket
address = '127.0.0.1' # The IP address to bind to
port = 8080 # The port to bind to
server_socket.bind((address, port))
# Listen on socket for up to 10 conections
server_socket.listen(10)
connection, addr = s.accept()
Called by a client to connect to a server/port
int Connect(int socket, (struct sockaddr *)&server_addr, socklen_t len)
socket
is the socket integer returned by socket()
server_addr
is what will hold the server details when connecting
len
is the pointer to the size of the server_addr struct
// Initialize socket
sock = socket(PF_INET, SOCK_STREAM, 0)
// Configure socket
struct sockaddr_in sock_config;
sock_config.sin_family = PF_INET; // IPV4 family address
sock_config.sin_port = htons(80); // port 80 or the common http port
sock_config.sin_addr.s_addr = INADDR_ANY;
bzero(&sock_config, 8);
// Bind socket
bind(sock, (struct sockaddr *)sock_config, sizeof(sock_config));
// Listen for up to 10 connections
listen(sock, 10)
// Accepting new connections
struct sockaddr_in client;
int len = sizeof(client);
Accept(sock, (struct sockaddr *)&client, &len);
// Connecting to a remote server
Connect(sock, (struct sockaddr *)&server_addr, len);
import socket
# Initialize socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # AF_INET == IPV4, SOCK_STREAM == TCP
# Bind Socket
address = '127.0.0.1' # The IP address to bind to
port = 8080 # The port to bind to
server_socket.bind((address, port))
# Listen on socket for up to 10 conections
server_socket.listen(10)
connection, addr = s.accept()
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 8080
int main(int argc, char const* argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = { 0 };
char* hello = "Hello from server";
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0))
== 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET,
SO_REUSEADDR | SO_REUSEPORT, &opt,
sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr*)&address,
sizeof(address))
< 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket
= accept(server_fd, (struct sockaddr*)&address,
(socklen_t*)&addrlen))
< 0) {
perror("accept");
exit(EXIT_FAILURE);
}
valread = read(new_socket, buffer, 1024);
printf("%s\n", buffer);
send(new_socket, hello, strlen(hello), 0);
printf("Hello message sent\n");
return 0;
}
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define PORT 8080
int main(int argc, char const* argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char* hello = "Hello from client";
char buffer[1024] = { 0 };
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary
// form
if (inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)
<= 0) {
printf(
"\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr*)&serv_addr,
sizeof(serv_addr))
< 0) {
printf("\nConnection Failed \n");
return -1;
}
send(sock, hello, strlen(hello), 0);
printf("Hello message sent\n");
valread = read(sock, buffer, 1024);
printf("%s\n", buffer);
return 0;
}
Example can be seen here:
https://github.com/Descent098/ezcv-http/tree/main/socket%20testing
Uses ezcv to generate html and then sockets as the http server