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

如何为C语言Socket服务器添加本地连接IP的端口扫描功能?

为你的C语言Socket服务器添加端口扫描功能

没问题,我帮你把端口扫描功能整合到现有的Socket服务器里。咱们先修正原代码里的一些小问题(比如不安全的gets函数),再补上完整的端口扫描逻辑,还能让你直接选择已连接的客户端IP来扫描,不用重复输入。

核心修改说明

  • 替换不安全的输入函数:把gets(hostname)换成更安全的输入方式,避免缓冲区溢出风险
  • 添加端口扫描核心函数:写一个scan_ports函数,负责遍历指定端口范围,尝试连接目标IP的端口并判断是否开放
  • 优化交互流程:让你可以直接选择已显示的客户端IP进行扫描,不用手动输入,更贴合你的需求

修改后的完整代码

#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>

#define MAX 80
#define PORT 8080
#define SA struct sockaddr

// 端口扫描函数:扫描目标IP的start到end端口
void scan_ports(const char* target_ip, int start_port, int end_port) {
    printf("\n开始扫描IP: %s,端口范围: %d-%d\n", target_ip, start_port, end_port);
    
    for (int port = start_port; port <= end_port; port++) {
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            perror("创建扫描socket失败");
            continue;
        }

        // 设置连接超时(避免长时间阻塞在未开放的端口)
        struct timeval timeout;
        timeout.tv_sec = 1;  // 1秒超时
        timeout.tv_usec = 0;
        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
        setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));

        struct sockaddr_in target_addr;
        memset(&target_addr, 0, sizeof(target_addr));
        target_addr.sin_family = AF_INET;
        target_addr.sin_port = htons(port);
        inet_pton(AF_INET, target_ip, &target_addr.sin_addr);

        // 尝试连接端口:连接成功则说明端口开放
        int result = connect(sock, (SA*)&target_addr, sizeof(target_addr));
        if (result == 0) {
            printf("端口 %d 开放\n", port);
        }

        close(sock);
    }
    printf("扫描完成\n");
}

// Driver function
int main() {
    int sockfd, connfd, len, start, end, choice;
    struct sockaddr_in servaddr, addr_remote;
    char ips[2][20];

    // socket create and verification
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        printf("socket creation failed...\n");
        exit(EXIT_FAILURE);
    } else {
        printf("Socket successfully created..\n");
    }

    bzero(&servaddr, sizeof(servaddr));
    // assign IP, PORT
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT);

    // Binding newly created socket to given IP and verification
    if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
        printf("socket bind failed...\n");
        exit(EXIT_FAILURE);
    } else {
        printf("Socket successfully binded..\n");
    }

    // Now server is ready to listen and verification
    if ((listen(sockfd, 5)) != 0) {
        printf("Listen failed...\n");
        exit(EXIT_FAILURE);
    } else {
        printf("Server listening..\n");
    }

    len = sizeof(addr_remote);
    // Accept up to 2 clients and store their IPs
    for (int i = 0; i < 2; i++) {
        connfd = accept(sockfd, (SA*)&addr_remote, &len);
        if (connfd < 0) {
            printf("server accept failed...\n");
            exit(EXIT_FAILURE);
        } else {
            printf("server accepted client %d...\n", i+1);
            strcpy(ips[i], inet_ntoa(addr_remote.sin_addr));
            close(connfd);  // 仅获取IP,不需要保持连接
        }
    }

    // Display connected client IPs
    printf("\n已连接的客户端IP列表:\n");
    for (int i = 0; i < 2; i++) {
        printf("%d. %s\n", i+1, ips[i]);
    }

    // 选择要扫描的IP
    printf("\n请选择要扫描的IP序号(1或2): ");
    scanf("%d", &choice);
    while (choice < 1 || choice > 2) {
        printf("无效序号,请重新输入(1或2): ");
        scanf("%d", &choice);
    }
    const char* target_ip = ips[choice-1];

    // Get start port number(带输入校验)
    printf("Enter start port number: ");
    while (scanf("%d", &start) != 1 || start < 1 || start > 65535) {
        printf("无效端口,请输入1-65535之间的数字: ");
        // 清除输入缓冲区的垃圾数据
        while (getchar() != '\n');
    }

    // Get end port number(带输入校验)
    printf("Enter end port number: ");
    while (scanf("%d", &end) != 1 || end < start || end > 65535) {
        printf("无效端口,请输入大于等于起始端口且<=65535的数字: ");
        while (getchar() != '\n');
    }

    // 执行端口扫描
    scan_ports(target_ip, start, end);

    // Close server socket
    close(sockfd);
    return 0;
}

关键功能说明

  1. 端口扫描逻辑:

    • 对每个端口创建独立的TCP socket,避免单个socket异常影响整个扫描流程
    • 设置1秒连接超时,防止程序在未开放的端口上长时间阻塞
    • 通过connect函数的返回值判断端口状态:连接成功则端口开放
  2. 输入校验优化:

    • 对端口输入做了范围校验(1-65535是TCP端口的合法范围)
    • 选择IP时做了序号校验,避免输入错误导致程序崩溃
  3. 资源管理:

    • 接受客户端连接后立即关闭connfd,因为我们只需要获取客户端IP
    • 每个扫描用的socket用完后及时关闭,避免系统资源泄漏

内容的提问来源于stack exchange,提问作者Salim Poui

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:03:25