您的位置:

Linux网络编程

一、基础概念

Linux网络编程涉及到一些基础概念,包括Socket、IP地址、端口等。Socket是Linux网络编程的核心,它是应用程序与网络协议之间的接口,可以进行网络通信。IP地址是网络中唯一标识一个主机的数值地址,通过它可以进行网络通信。而端口是用于标识一个应用程序的地址,只有在同一IP地址下,不同端口的应用程序才能进行通信。

下面是基于Socket的简单TCP服务器端代码示例:

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

int main()
{
    // 创建socket
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);

    // 设置socket运行参数
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(9002);
    server_address.sin_addr.s_addr = INADDR_ANY;

    // 绑定socket
    bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address));

    // 监听socket
    listen(server_socket, 5);

    // 等待客户端连接
    int client_socket = accept(server_socket, NULL, NULL);

    // 向客户端发送消息
    char message[] = "Hello, World!";
    send(client_socket, message, sizeof(message), 0);

    // 关闭socket
    close(client_socket);
    close(server_socket);

    return 0;
}

二、套接字编程

Linux网络编程中,套接字编程是最常用的编程方式。套接字编程使用Socket接口,通过系统调用Bind、Listen、Accept、Connect、Recv、Send等方法实现网络通信,包括TCP、UDP、Raw Socket等多种协议。

下面是基于Socket的简单TCP客户端代码示例:

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

int main()
{
    // 创建socket
    int client_socket = socket(AF_INET, SOCK_STREAM, 0);

    // 设置socket运行参数
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(9002);
    inet_pton(AF_INET, "127.0.0.1", &server_address.sin_addr);

    // 连接服务器
    connect(client_socket, (struct sockaddr*)&server_address, sizeof(server_address));

    // 接收服务器消息
    char message[100];
    recv(client_socket, message, 100, 0);

    // 输出服务器消息
    printf("%s\n", message);

    // 关闭socket
    close(client_socket);

    return 0;
}

三、网络通信协议

一个网络应用系统中,各个层次之间通信需要遵循不同的协议,包括物理层协议、数据链路层协议、网络层协议、传输层协议和应用层协议。Linux网络编程涉及到的主要协议有TCP/IP协议、UDP协议、ICMP协议、ARP协议等。其中,TCP/IP协议是最常用的网络通信协议,它实现了可靠的数据传输,可以确保数据的正确性。

下面是基于Socket的简单UDP服务器端代码示例:

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

int main()
{
    // 创建socket
    int server_socket = socket(AF_INET, SOCK_DGRAM, 0);

    // 设置socket运行参数
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(9003);
    server_address.sin_addr.s_addr = INADDR_ANY;

    // 绑定socket
    bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address));

    // 接收客户端消息
    char message[100];
    struct sockaddr_in client_address;
    socklen_t client_length = sizeof(client_address);
    recvfrom(server_socket, message, 100, 0, (struct sockaddr*)&client_address, &client_length);

    // 输出客户端IP地址及消息内容
    printf("Message from [%s]: %s\n", inet_ntoa(client_address.sin_addr), message);

    // 关闭socket
    close(server_socket);

    return 0;
}

下面是基于Socket的简单UDP客户端代码示例:

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

int main()
{
    // 创建socket
    int client_socket = socket(AF_INET, SOCK_DGRAM, 0);

    // 设置socket运行参数
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(9003);
    server_address.sin_addr.s_addr = inet_addr("127.0.0.1");

    // 发送消息到服务器
    char message[] = "Hello, server!";
    sendto(client_socket, message, sizeof(message), 0, (struct sockaddr*)&server_address, sizeof(server_address));

    // 关闭socket
    close(client_socket);

    return 0;
}

四、多线程网络编程

多线程网络编程是指在一个进程中,启动多个线程来处理网络请求。它可以提高程序并发处理能力,同时也需要注意线程间的同步、互斥等问题。

下面是基于Socket的简单多线程TCP服务器端代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>

void* handle_client(void* arg)
{
    // 接收客户端消息
    char message[100];
    int client_socket = *((int*)arg);
    recv(client_socket, message, 100, 0);

    // 输出客户端消息
    printf("%s\n", message);

    // 向客户端发送消息
    char reply[] = "I have received your message!";
    send(client_socket, reply, sizeof(reply), 0);

    // 关闭socket
    close(client_socket);

    return NULL;
}

int main()
{
    // 创建socket
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);

    // 设置socket运行参数
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(9004);
    server_address.sin_addr.s_addr = INADDR_ANY;

    // 绑定socket
    bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address));

    // 监听socket
    listen(server_socket, 5);

    // 创建线程处理客户端请求
    pthread_t thread_id;
    while(1)
    {
        int client_socket = accept(server_socket, NULL, NULL);
        pthread_create(&thread_id, NULL, handle_client, &client_socket);
    }

    // 关闭socket
    close(server_socket);

    return 0;
}

五、网络安全编程

Linux网络编程中,网络安全编程是十分重要的内容。网络安全编程主要包括SSL/TLS协议、数字签名、加解密等技术,可以保证网络通信的安全性。

下面是基于SSL/TLS协议的简单TCP服务器端代码示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

void init_openssl()
{
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
}

void cleanup_openssl()
{
    ERR_free_strings();
    EVP_cleanup();
    CRYPTO_cleanup_all_ex_data();
}

SSL_CTX* create_context()
{
    const SSL_METHOD* method;
    SSL_CTX* ctx;

    method = TLSv1_2_server_method();

    ctx = SSL_CTX_new(method);
    if (!ctx)
    {
        perror("Unable to create SSL context");
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    return ctx;
}

void configure_context(SSL_CTX* ctx)
{
    SSL_CTX_set_ecdh_auto(ctx, 1);

    if (SSL_CTX_use_certificate_file(ctx, "cert.pem", SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }

    if (SSL_CTX_use_PrivateKey_file(ctx, "key.pem", SSL_FILETYPE_PEM) <= 0 )
    {
        ERR_print_errors_fp(stderr);
        exit(EXIT_FAILURE);
    }
}

int main()
{
    // 初始化OpenSSL
    SSL_CTX* ctx;
    init_openssl();
    ctx = create_context();
    configure_context(ctx);

    // 创建socket
    int server_socket = socket(AF_INET, SOCK_STREAM, 0);

    // 设置socket运行参数
    struct sockaddr_in server_address;
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(9005);
    server_address.sin_addr.s_addr = INADDR_ANY;

    // 绑定socket
    bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address));

    // 监听socket
    listen(server_socket, 5);

    // 接收客户端连接并进行SSL握手
    while(1)
    {
        struct sockaddr_in client_address;
        unsigned int client_length = sizeof(client_address);
        int client_socket = accept(server_socket, (struct sockaddr*)&client_address, &client_length);

        SSL* ssl = SSL_new(ctx);
        SSL_set_fd(ssl, client_socket);

        if (SSL_accept(ssl) <= 0)
        {
            ERR_print_errors_fp(stderr);
        }
        else
        {
            // 向客户端发送消息
            char message[] = "Hello, World!";
            SSL_write(ssl, message, sizeof(message));

            // 接收客户端消息
            char buffer[100];
            SSL_read(ssl, buffer, 100);
            printf("Client message: %s\n", buffer);
        }

        // 关闭SSL连接
        SSL_shutdown(ssl);
        SSL_free(ssl);

        // 关闭socket
        close(client_socket);
    }

    // 关闭socket
    close(server_socket);

    // 清理OpenSSL
    cleanup_openssl();

    return 0;
}