High-performance TCP mock server

If you need a high-performance TCP mock server that:

  1. Handles plain TCP connections (not HTTP).
  2. Reads incoming requests where the first 8 characters represent the length of the request.
  3. Efficiently handles thousands of connections with minimal overhead.
  4. Uses epoll for high TPS (Linux).

Optimized Approach

  • epoll for Non-blocking I/O: Handles multiple clients efficiently.
  • read() loop: Ensures full request reception.
  • send() for fixed response: No complex logic, just echoing back.
  • No fork or threads: Single-threaded, event-driven for maximum TPS.

High-Performance Plain TCP Mock Server in C

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <arpa/inet.h>

#define PORT 8080
#define MAX_EVENTS 1024
#define BUFFER_SIZE 8192
#define RESPONSE "MOCK_RESPONSE"

void set_nonblocking(int sock) {
    int flags = fcntl(sock, F_GETFL, 0);
    fcntl(sock, F_SETFL, flags | O_NONBLOCK);
}

int parse_length(const char *buffer) {
    char len_str[9] = {0}; // 8 characters + null terminator
    strncpy(len_str, buffer, 8);
    return atoi(len_str);
}

int main() {
    int server_fd, client_fd, epoll_fd;
    struct sockaddr_in server_addr, client_addr;
    struct epoll_event event, events[MAX_EVENTS];
    socklen_t client_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE];

    // Create TCP socket
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("Socket failed");
        exit(EXIT_FAILURE);
    }

    // Allow immediate reuse of the port
    int opt = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    // Bind to port
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);
    bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));

    // Start listening
    listen(server_fd, SOMAXCONN);
    set_nonblocking(server_fd);

    // Setup epoll
    epoll_fd = epoll_create1(0);
    event.events = EPOLLIN;
    event.data.fd = server_fd;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, server_fd, &event);

    printf("Mock TCP server listening on port %d\n", PORT);

    while (1) {
        int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
        for (int i = 0; i < num_events; i++) {
            if (events[i].data.fd == server_fd) {
                // Accept new connections
                while ((client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len)) > 0) {
                    set_nonblocking(client_fd);
                    event.events = EPOLLIN | EPOLLET;
                    event.data.fd = client_fd;
                    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, client_fd, &event);
                }
            } else {
                // Handle client request
                client_fd = events[i].data.fd;
                int total_read = 0, request_length = -1;
                
                while (1) {
                    int bytes_read = read(client_fd, buffer + total_read, BUFFER_SIZE - total_read);
                    if (bytes_read <= 0) break; // No more data to read
                    
                    total_read += bytes_read;
                    
                    if (total_read >= 8 && request_length == -1) {
                        // Extract length from first 8 characters
                        request_length = parse_length(buffer);
                    }

                    // Ensure the full request is read
                    if (request_length != -1 && total_read >= request_length) {
                        send(client_fd, RESPONSE, sizeof(RESPONSE) - 1, 0);
                        close(client_fd); // Close connection after responding
                        break;
                    }
                }
            }
        }
    }

    close(server_fd);
    return 0;
}

How It Works

  1. TCP Socket Setup:

    • Creates a non-blocking server socket (server_fd).
    • Uses SO_REUSEADDR for fast restarts.
    • Uses epoll to efficiently handle multiple connections.
  2. Client Handling:

    • Accepts connections and makes them non-blocking.
    • Reads incoming data until full request is received.
    • Extracts request length from the first 8 bytes.
    • Waits until the full request is read before responding.
    • Sends "MOCK_RESPONSE" and closes the connection.

Performance Enhancements

epoll for High TPS (scalable event loop).

Non-blocking Sockets (handles thousands of clients).

Minimal Memory Copying (only processes request length).

No malloc() or Dynamic Memory (avoids fragmentation).

Auto-closes Connections After Response (mock behavior).

This should easily handle 100K+ TPS on a decent server. 🚀

You would consider multi-threading (SO_REUSEPORT) or io_uring for even higher performance

相关推荐
白帽黑客沐瑶2 天前
【网络安全就业】信息安全专业的就业前景(非常详细)零基础入门到精通,收藏这篇就够了
网络·安全·web安全·计算机·程序员·编程·网络安全就业
树码小子2 天前
Java网络编程:(socket API编程:TCP协议的 socket API -- 回显程序的服务器端程序的编写)
java·网络·tcp/ip
绿箭柠檬茶2 天前
Ubuntu 服务器配置转发网络访问
服务器·网络·ubuntu
FPGA_Linuxer2 天前
FPGA 40 DAC线缆和光模块带光纤实现40G UDP差异
网络协议·fpga开发·udp
real 12 天前
传输层协议UDP
网络·网络协议·udp
路由侠内网穿透2 天前
本地部署 GPS 跟踪系统 Traccar 并实现外部访问
运维·服务器·网络·windows·tcp/ip
喵手3 天前
玩转Java网络编程:基于Socket的服务器和客户端开发!
java·服务器·网络
徐子元竟然被占了!!3 天前
实验-基本ACL
网络
ftpeak3 天前
从零开始使用 axum-server 构建 HTTP/HTTPS 服务
网络·http·https·rust·web·web app
LabVIEW开发3 天前
LabVIEW气体污染无线监测
网络·labview·labview知识·labview功能·labview程序