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

相关推荐
buyutang_20 小时前
Linux 网络编程:深度理解网络字节序与主机字节序、大端字节序与小端字节序
linux·运维·网络
姓蔡小朋友20 小时前
Redis网络I/O模型
网络·数据库·redis
量子物理学20 小时前
openssl自建CA并生成自签名SSL证书
网络·网络协议·ssl
成空的梦想20 小时前
除了加密,它还能验明正身:SSL如何防范网络钓鱼?
网络·https·ssl
honsor1 天前
精准监测 + 实时传输!网络型温湿度传感器,筑牢环境数据管理防线
网络·物联网
张人玉1 天前
Https协议数据格式
网络协议·http·https
专家大圣1 天前
远程调式不复杂!内网服务器调试用对工具很简单
运维·服务器·网络·内网穿透·cpolar
拾忆,想起1 天前
Dubbo配置方式大全:七种配置任你选,轻松玩转微服务!
服务器·网络·网络协议·微服务·云原生·架构·dubbo
2501_941142931 天前
云原生微服务环境下服务熔断与降级优化实践——提升系统稳定性与容错能力
java·大数据·网络
国科安芯1 天前
航天医疗领域AS32S601芯片的性能分析与适配性探讨
大数据·网络·人工智能·单片机·嵌入式硬件·fpga开发·性能优化