Created
February 3, 2024 22:18
-
-
Save umputun/9992a1747b9080ea2f301a6f37822aec to your computer and use it in GitHub Desktop.
pong server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <sys/time.h> | |
#define PORT 8080 | |
#define BUFFER_SIZE 1024 | |
#define REQUEST_INTERVAL 500000 // 500 milliseconds in microseconds | |
void handleConnection(int newSocket, const char *info) { | |
char buffer[BUFFER_SIZE] = {0}; // Initialize buffer to zeros | |
char response[2048]; | |
ssize_t bytesRead = read(newSocket, buffer, BUFFER_SIZE - 1); // Leave space for null terminator | |
if (bytesRead < 0) { | |
perror("read"); | |
return; | |
} | |
buffer[bytesRead] = '\0'; // Null-terminate the buffer | |
if (strstr(buffer, "GET /ping HTTP/1.1")) { | |
snprintf(response, sizeof(response), | |
"HTTP/1.1 200 OK\r\n" | |
"Content-Type: text/html; charset=UTF-8\r\n" | |
"Server: %s\r\n\r\n" | |
"pong\r\n", info); | |
} else { | |
snprintf(response, sizeof(response), | |
"HTTP/1.1 404 Not Found\r\n" | |
"Content-Type: text/html; charset=UTF-8\r\n" | |
"Server: %s\r\n\r\n" | |
"Not Found\r\n", info); | |
} | |
send(newSocket, response, strlen(response), 0); | |
close(newSocket); | |
} | |
int main(int argc, char *argv[]) { | |
int serverFd, newSocket; | |
struct sockaddr_in address; | |
int opt = 1; | |
int addrlen = sizeof(address); | |
if (argc < 2) { | |
printf("Usage: %s <server-info>\n", argv[0]); | |
return 1; | |
} | |
const char *info = argv[1]; | |
serverFd = socket(AF_INET, SOCK_STREAM, 0); | |
if (serverFd == 0) { | |
perror("socket failed"); | |
exit(EXIT_FAILURE); | |
} | |
if (setsockopt(serverFd, 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); | |
if (bind(serverFd, (struct sockaddr *)&address, sizeof(address)) < 0) { | |
perror("bind failed"); | |
exit(EXIT_FAILURE); | |
} | |
if (listen(serverFd, 10) < 0) { | |
perror("listen"); | |
exit(EXIT_FAILURE); | |
} | |
struct timeval lastRequestTime, currentTime; | |
gettimeofday(&lastRequestTime, NULL); // Initialize lastRequestTime | |
printf("pong server is running for %s\n", info); | |
while (1) { | |
newSocket = accept(serverFd, (struct sockaddr *)&address, (socklen_t*)&addrlen); | |
if (newSocket < 0) { | |
perror("accept"); | |
continue; | |
} | |
gettimeofday(¤tTime, NULL); | |
long elapsed = (currentTime.tv_sec - lastRequestTime.tv_sec) * 1000000L | |
+ (currentTime.tv_usec - lastRequestTime.tv_usec); | |
if (elapsed < REQUEST_INTERVAL) { | |
usleep(REQUEST_INTERVAL - elapsed); // Delay the response | |
} | |
lastRequestTime = currentTime; | |
handleConnection(newSocket, info); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment