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

相关推荐
出海探索的Cindy5 小时前
什么是IP隔离?一文讲清跨境电商/海外社媒的IP隔离逻辑
网络·网络协议·tcp/ip
搬码临时工6 小时前
通过自定义域名访问内网的web服务和tcp应用:内网ip到局域网外域名访问过程
服务器·tcp/ip·php
我再也不搞抽象了6 小时前
网络与信息安全有哪些岗位:(6)安全开发工程师
网络·安全
wanhengidc7 小时前
造成云手机闪退的原因有哪些?
服务器·网络·安全·智能手机·媒体
聚铭网络9 小时前
聚铭安全管家平台2.0实战解码 | 安服篇(四):重构威胁追溯体系
网络·安全·重构
郭二哈9 小时前
git的使用
大数据·网络·git·elasticsearch
zcz160712782111 小时前
Linux 网络命令大全
linux·运维·网络
VVVVWeiYee11 小时前
BGP高级特性
运维·服务器·网络
subuq13 小时前
Web3.0 时代的电商系统:区块链如何解决信任与溯源问题?
大数据·网络·学习
安卓开发者13 小时前
Android中使用RxJava实现网络请求与缓存策略
android·网络·rxjava