├── README.md
├── index.html
└── reverse_proxy.c
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Multithreaded Reverse Proxy Server in C
3 |
4 | ## Introduction
5 |
6 | This repository contains the source code for a **Multithreaded Reverse Proxy Server** built in C. The server acts as an intermediary for requests from clients seeking resources from backend servers. It is just a basic verson, but we can make it much more advanced.
7 |
8 | ## Features
9 |
10 | - **Multithreading Support:** Uses a thread pool or dynamically spawns threads to handle multiple concurrent client connections.
11 | - **Load Balancing:** Distributes incoming requests to multiple backend servers based on algorithms like round-robin or least connections (if implemented).
12 | - **Connection Persistence:** Supports persistent connections to backend servers for efficiency (if HTTP/1.1 Keep-Alive is implemented).
13 | - **Customizable Configuration:** Allows configuration of port, backend servers, thread pool size, and more.
14 | - **Request/Response Logging:** Logs client requests and responses from backend servers for debugging and analysis.
15 | - **Error Handling:** Gracefully handles client and server errors, including timeouts and malformed requests.
16 |
17 | ## Prerequisites
18 |
19 | Before running the project, ensure you have the following:
20 |
21 | - **C Compiler:** GCC or Clang.
22 | - **POSIX Threads (pthread):** Required for multithreading.
23 | - **Linux Environment:** Tested on Linux-based systems.
24 |
25 |
26 | ## Installation and Setup (In progress)
27 | 1. Build using WSL and VScode.
28 |
29 |
30 | ## How It Works
31 |
32 | 1. **Initialization:**
33 | - The server reads the configuration file to initialize settings.
34 | - A thread pool is created to handle client connections.
35 |
36 | 2. **Client Connection Handling:**
37 | - The server listens on the specified port for client connections.
38 | - Each incoming connection is assigned to a thread in the thread pool.
39 |
40 | 3. **Request Forwarding:**
41 | - The proxy server parses the client request and forwards it to a backend server.
42 | - The backend server processes the request and sends the response back to the proxy server.
43 |
44 | 4. **Response Delivery:**
45 | - The proxy server relays the response from the backend server to the client.
46 |
47 | ## Contributing
48 |
49 | Contributions are welcome! If you'd like to improve this project, feel free to submit a pull request or open an issue.
50 |
51 | ## License
52 |
53 | This project is licensed under no License. You are free to use, modify, and distribute this software as per you.
54 |
55 | ## Acknowledgments
56 |
57 | - **POSIX Threads Documentation:** For threading implementation.
58 | - **C Networking Tutorials:** For socket programming techniques.
59 | - **Open Source Community:** For various libraries and inspirations.
60 |
61 | ---
62 | ### Further readme will be done in coming days and it will be veyr useful and it can make a lot better and finally.
63 |
64 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Reverse Proxy Server
9 |
10 |
11 |
12 | This is an Example as a test to be successful test 😇🎉🎉
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/reverse_proxy.c:
--------------------------------------------------------------------------------
1 | // 😇Let's build a "Basic Multithreaded Reverse Proxy Server in C from Scratch"
2 | // 1. Under 130+ lines.
3 | // 2. Great for understanding the fundamentals.
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #define BUFFER_SIZE 8192
14 | #define PORT 8080
15 |
16 | typedef struct {
17 | int client_sock;
18 | } thread_args_t;
19 |
20 | // Updated handle_client function
21 | void *handle_client(void *args) {
22 | thread_args_t *client_args = (thread_args_t *)args;
23 | int client_sock = client_args->client_sock;
24 |
25 | // Serve a static file (index.html)
26 | const char *file_path = "/mnt/c/Users/Abhishek Kumar/Desktop/Multithreaded_reverse_proxy_in_c/index.html"; //write your own path
27 | FILE *file = fopen(file_path, "r");
28 | if (!file) {
29 | perror("Failed to open file");
30 | const char *error_response =
31 | "HTTP/1.1 404 Not Found\r\n"
32 | "Content-Type: text/plain\r\n"
33 | "Content-Length: 13\r\n"
34 | "\r\n"
35 | "404 Not Found";
36 | send(client_sock, error_response, strlen(error_response), 0);
37 | close(client_sock);
38 | free(client_args);
39 | return NULL;
40 | }
41 |
42 | // Read the contents of the file
43 | char file_buffer[4096];
44 | size_t file_size = fread(file_buffer, 1, sizeof(file_buffer), file);
45 | fclose(file);
46 |
47 | // Prepare and send the HTTP response
48 | char response_header[256];
49 | snprintf(response_header, sizeof(response_header),
50 | "HTTP/1.1 200 OK\r\n"
51 | "Content-Type: text/html\r\n"
52 | "Content-Length: %zu\r\n"
53 | "\r\n",
54 | file_size);
55 |
56 | send(client_sock, response_header, strlen(response_header), 0);
57 | send(client_sock, file_buffer, file_size, 0);
58 |
59 | // Clean up and close the connection
60 | close(client_sock);
61 | free(client_args);
62 |
63 | return NULL;
64 |
65 | }
66 |
67 | // Main function from where everything got started
68 |
69 | int main() {
70 | int server_sock;
71 | struct sockaddr_in server_addr;
72 |
73 | // Create the server socket
74 | server_sock = socket(AF_INET, SOCK_STREAM, 0);
75 | if (server_sock <0) {
76 | perror("Failed to create sockt");
77 | exit(EXIT_FAILURE);
78 | }
79 |
80 | // Configure the server address
81 | server_addr.sin_family = AF_INET;
82 | server_addr.sin_port = htons(PORT);
83 | server_addr.sin_addr.s_addr = INADDR_ANY;
84 |
85 | // Bind the socket to the address and port
86 | if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
87 | perror("Failed to bind");
88 | close(server_sock);
89 | exit(EXIT_FAILURE);
90 |
91 | }
92 |
93 | // Start listening for incoming connections
94 | if (listen(server_sock, 10) < 0) {
95 | perror("Failed to listen");
96 | close(server_sock);
97 | exit(EXIT_FAILURE);
98 |
99 | }
100 |
101 | printf("Reverse proxy server running on port %d...\n", PORT);
102 |
103 | // Main loop to handle client connections
104 | while (1) {
105 | struct sockaddr_in client_addr;
106 | socklen_t client_len = sizeof(client_addr);
107 |
108 | // Accept a new client connection
109 | int client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &client_len);
110 | if (client_sock < 0) {
111 | perror("Failed to accept connection");
112 | continue;
113 | }
114 |
115 |
116 | // Allocate memory for thread arguments
117 | thread_args_t *args = malloc(sizeof(thread_args_t));
118 | if(!args) {
119 | perror("Failed to allocate memory for thread arguments");
120 | close(client_sock);
121 | continue;
122 | }
123 | args->client_sock = client_sock;
124 |
125 | // Create a new thread to handle the client
126 | pthread_t thread_id;
127 | if(pthread_create(&thread_id, NULL, handle_client, args) != 0) {
128 | perror("Failed to create thread");
129 | close(client_sock);
130 | free(args);
131 | continue;
132 | }
133 |
134 | // Detach the thread to allow it to clean up its resources
135 | pthread_detach(thread_id);
136 | }
137 |
138 | // Close the server socket
139 | close(server_sock);
140 | return 0;
141 |
142 | }
143 |
144 | // Finally it's complete, let's check it on terminal.
145 | // Now let's write HTML code, to see the result.
146 | // Now open terminal
147 |
148 |
--------------------------------------------------------------------------------