You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于C语言ncurses UI的聊天程序Socket收发数据异常求助

Hey Andrew, let's break down this socket/ncurses issue you're facing—those weird escape characters and truncated usernames are definitely frustrating, but let's tackle them step by step.

First, Let's Recap the Core Issues

  • Client-side anomaly: Short usernames (<6 characters) display with random escape characters (e.g., a^C^\^?^U^D: test message).
  • Server-side anomaly: Usernames shorter than 4 characters get truncated (e.g., input qw shows as q).
  • Suspected root causes: Socket data handling, ncurses input processing, or string manipulation bugs.

Most Likely Root Causes & Fixes

1. Ncurses is Leaking Control Characters Into Your Username Input

Ncurses operates in raw/cbreak mode by default, which captures control keys (like backspace, Ctrl+C) as ASCII control characters (values <32). If your client's send_uname function doesn't filter these, they get sent to the server and broadcasted as garbage.

Fix Steps for Client Input:

  • Add a filter to only keep printable ASCII characters (32–126) and handle backspace properly:
    void send_uname(int socket) {
        char uname[256] = {0}; // Initialize buffer to zero
        int ch, idx = 0;
        cbreak(); // Disable line buffering
        noecho(); // Handle echo manually to avoid control chars showing
    
        while ((ch = getch()) != '\n' && idx < sizeof(uname)-1) {
            // Keep only printable characters
            if (ch >= 32 && ch <= 126) {
                uname[idx++] = ch;
                addch(ch); // Echo valid character to screen
                refresh();
            }
            // Handle backspace (ALT_BACKSPACE = 127)
            else if (ch == ALT_BACKSPACE && idx > 0) {
                idx--;
                move(getcury(stdscr), getcurx(stdscr)-1);
                delch();
                refresh();
            }
        }
        uname[idx] = '\0'; // Ensure string is null-terminated
        // Send username including null terminator to server
        send(socket, uname, strlen(uname)+1, 0);
    }
    
  • Verify your check_buff function is actually filtering control characters—if it's not, replace or augment it with the logic above.

2. Socket Receive Logic Isn't Handling Null Termination or Partial Reads

TCP is a stream protocol, so recv() may not return the full username in one call. Plus, if your server's recv_uname doesn't manually add a null terminator, it'll read garbage data from memory (those escape characters) when processing short usernames.

Fix Steps for Server Username Receiving:

void recv_uname(int socket, char* uname) {
    const size_t BUF_SIZE = 256;
    memset(uname, 0, BUF_SIZE); // Clear buffer first
    ssize_t bytes_read = recv(socket, uname, BUF_SIZE-1, 0); // Leave space for null terminator

    if (bytes_read > 0) {
        uname[bytes_read] = '\0'; // Force null termination
        // Optional: Double-filter control chars in case client missed any
        char* clean_ptr = uname;
        for (char* ptr = uname; *ptr != '\0'; ptr++) {
            if (*ptr >= 32 && *ptr <= 126) {
                *clean_ptr++ = *ptr;
            }
        }
        *clean_ptr = '\0';
    }
}
  • The truncation issue (e.g., qw → q) likely happens because your original recv_uname was stopping at a stray control character (like a leftover \r or \0 from a previous input). The filter above eliminates that.

3. Broadcast String Manipulation is Unsafe

Using strcat or manual string concatenation without buffer bounds checking can lead to overflow and garbage data. Use snprintf instead for safe formatting:

void transmitt(int socket, int index) {
    // Assume you have access to the client's username and incoming message
    char broadcast_msg[512] = {0};
    snprintf(broadcast_msg, sizeof(broadcast_msg), "%s: %s", client_usernames[index], incoming_msg);
    // Send broadcast_msg to all connected clients...
}

Debugging Tips to Confirm

  • Add debug prints in send_uname to log each byte's ASCII value before sending (e.g., printf("Byte %d: %d ('%c')\n", idx, uname[idx], uname[idx]);). This will show if control chars are slipping through.
  • On the server, print the raw received username bytes after recv() to see if truncation is happening during reception or later processing.

内容的提问来源于stack exchange,提问作者Andrew Wilbik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:49:56