MST

星途 面试题库

面试题:C语言中Linux Socket连接管理之错误处理

在Linux C语言Socket编程进行连接管理时,常见的连接错误有哪些?请至少列举3种,并说明如何在代码中对这些错误进行捕获和处理。
42.9万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

常见连接错误

  1. 连接超时:由于网络延迟、服务器负载高等原因,客户端在规定时间内未能与服务器建立连接。
  2. 连接被拒绝:通常是因为服务器未在指定端口监听,或者防火墙阻止了连接。
  3. 地址错误:包括IP地址错误、端口号错误等,导致无法定位到目标服务器。

错误捕获与处理

连接超时

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <errno.h>

#define PORT 8080
#define IP "127.0.0.1"
#define TIMEOUT_SECONDS 3

int main(int argc, char const *argv[]) {
    int sock = 0, valread;
    struct sockaddr_in serv_addr;
    struct timeval timeout;
    timeout.tv_sec = TIMEOUT_SECONDS;
    timeout.tv_usec = 0;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    serv_addr.sin_addr.s_addr = inet_addr(IP);

    if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (const char *)&timeout, sizeof(timeout)) < 0) {
        perror("setsockopt failed");
        close(sock);
        exit(EXIT_FAILURE);
    }

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        if (errno == EINPROGRESS) {
            printf("Connection timed out\n");
        } else {
            perror("connect failed");
        }
        close(sock);
        exit(EXIT_FAILURE);
    }

    // 连接成功后的操作
    close(sock);
    return 0;
}

在上述代码中,通过 setsockopt 设置了连接的发送超时时间,在 connect 失败后,通过检查 errno 是否为 EINPROGRESS 判断是否连接超时。

连接被拒绝

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

#define PORT 8080
#define IP "127.0.0.1"

int main(int argc, char const *argv[]) {
    int sock = 0, valread;
    struct sockaddr_in serv_addr;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    serv_addr.sin_addr.s_addr = inet_addr(IP);

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        if (errno == ECONNREFUSED) {
            printf("Connection refused\n");
        } else {
            perror("connect failed");
        }
        close(sock);
        exit(EXIT_FAILURE);
    }

    // 连接成功后的操作
    close(sock);
    return 0;
}

这里在 connect 失败后,通过检查 errno 是否为 ECONNREFUSED 判断是否连接被拒绝。

地址错误

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

#define PORT 8080
#define IP "127.0.0.256" // 错误的IP地址

int main(int argc, char const *argv[]) {
    int sock = 0, valread;
    struct sockaddr_in serv_addr;

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("socket creation failed");
        exit(EXIT_FAILURE);
    }

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    if (inet_pton(AF_INET, IP, &serv_addr.sin_addr) <= 0) {
        printf("Invalid address/ Address not supported \n");
        close(sock);
        exit(EXIT_FAILURE);
    }

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("connect failed");
        close(sock);
        exit(EXIT_FAILURE);
    }

    // 连接成功后的操作
    close(sock);
    return 0;
}

在设置服务器地址时,通过 inet_pton 函数检查IP地址的有效性,如果返回值小于等于0,则说明地址无效。在 connect 失败后,通过 perror 输出错误信息,可从中发现地址相关错误。