• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

twilight0966

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

2025-2026-1 20231301 《信息安全设计》第十一周学习总结

2025-2026-1 20231301 《信息安全设计》第十一周学习总结

目录
  • 作业信息
  • 学习内容总结
    • 网络编程核心概念
      • 1. 套接字类型与协议
      • 2. 完整的TCP服务器实现
      • 3. 高级客户端实现
    • 并发服务器架构
      • 多进程并发服务器
    • 思维导图

作业信息

作业 链接
作业课程 <班级>(2025-2026-1 信息安全设计)
作业要求 <作业>(2025-2026-1 信息安全设计 预习作业要求)
作业目标 《Head First C 嗨翻C语⾔》> 预习第十一章
作业正文 <博客>(第十一周学习总结)

学习内容总结

第十一章:套接字与网络编程

网络编程核心概念

1. 套接字类型与协议

#include <sys/socket.h>

void socket_types_demo() {
    // 流式套接字 (TCP)
    int tcp_socket = socket(PF_INET, SOCK_STREAM, 0);
    
    // 数据报套接字 (UDP)  
    int udp_socket = socket(PF_INET, SOCK_DGRAM, 0);
    
    // 原始套接字 (直接IP访问)
    int raw_socket = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
    
    printf("TCP socket: %d\n", tcp_socket);
    printf("UDP socket: %d\n", udp_socket);
    
    close(tcp_socket);
    close(udp_socket);
}

2. 完整的TCP服务器实现

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

#define PORT 8080
#define BUFFER_SIZE 1024

void tcp_echo_server() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int opt = 1;
    int addrlen = sizeof(address);
    char buffer[BUFFER_SIZE] = {0};
    
    // 创建套接字文件描述符
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
    
    // 设置套接字选项
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
        perror("setsockopt");
        exit(EXIT_FAILURE);
    }
    
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);
    
    // 绑定套接字到端口
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    
    // 开始监听
    if (listen(server_fd, 3) < 0) {
        perror("listen");
        exit(EXIT_FAILURE);
    }
    
    printf("Server listening on port %d\n", PORT);
    
    while (1) {
        printf("Waiting for connections...\n");
        
        if ((new_socket = accept(server_fd, (struct sockaddr *)&address, 
                               (socklen_t*)&addrlen)) < 0) {
            perror("accept");
            exit(EXIT_FAILURE);
        }
        
        printf("Connection accepted from %s:%d\n", 
               inet_ntoa(address.sin_addr), ntohs(address.sin_port));
        
        // 读取客户端数据
        ssize_t valread = read(new_socket, buffer, BUFFER_SIZE);
        printf("Received: %s\n", buffer);
        
        // 发送响应
        const char* response = "Hello from server";
        send(new_socket, response, strlen(response), 0);
        printf("Response sent\n");
        
        close(new_socket);
    }
    
    close(server_fd);
}

3. 高级客户端实现

#include <netdb.h>

int create_connected_socket(const char* hostname, const char* port) {
    struct addrinfo hints, *result, *rp;
    int sockfd;
    
    memset(&hints, 0, sizeof(hints));
    hints.ai_family = AF_UNSPEC;    // IPv4 或 IPv6
    hints.ai_socktype = SOCK_STREAM; // TCP 套接字
    
    // 解析主机名和服务名
    int status = getaddrinfo(hostname, port, &hints, &result);
    if (status != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
        return -1;
    }
    
    // 尝试每个地址直到成功连接
    for (rp = result; rp != NULL; rp = rp->ai_next) {
        sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (sockfd == -1)
            continue;
            
        if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1)
            break; // 成功连接
            
        close(sockfd); // 连接失败,关闭套接字继续尝试
    }
    
    freeaddrinfo(result);
    
    if (rp == NULL) {
        fprintf(stderr, "Could not connect to %s:%s\n", hostname, port);
        return -1;
    }
    
    return sockfd;
}

void http_client_demo() {
    int sockfd = create_connected_socket("www.example.com", "80");
    if (sockfd == -1) return;
    
    // 发送 HTTP 请求
    const char* http_request = 
        "GET / HTTP/1.1\r\n"
        "Host: www.example.com\r\n"
        "Connection: close\r\n"
        "\r\n";
    
    if (send(sockfd, http_request, strlen(http_request), 0) == -1) {
        perror("send");
        close(sockfd);
        return;
    }
    
    // 接收响应
    char buffer[4096];
    ssize_t bytes_received;
    
    printf("HTTP Response:\n");
    while ((bytes_received = recv(sockfd, buffer, sizeof(buffer)-1, 0)) > 0) {
        buffer[bytes_received] = '\0';
        printf("%s", buffer);
    }
    
    close(sockfd);
}

并发服务器架构

多进程并发服务器

void concurrent_server() {
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    // ... 绑定和监听代码同上
    
    while (1) {
        int client_socket = accept(server_fd, NULL, NULL);
        if (client_socket < 0) {
            perror("accept");
            continue;
        }
        
        pid_t pid = fork();
        if (pid == 0) {
            // 子进程
            close(server_fd); // 子进程不需要监听套接字
            
            handle_client(client_socket);
            close(client_socket);
            _exit(0);
        } else if (pid > 0) {
            // 父进程
            close(client_socket); // 父进程不需要客户端套接字
        } else {
            perror("fork");
            close(client_socket);
        }
    }
}

void handle_client(int client_socket) {
    char buffer[1024];
    ssize_t bytes_read;
    
    // 处理客户端请求
    while ((bytes_read = recv(client_socket, buffer, sizeof(buffer), 0)) > 0) {
        // 处理数据...
        send(client_socket, buffer, bytes_read, 0);
    }
}

思维导图

截屏2025-09-30 下午10.02

posted on 2025-09-30 22:02  20231301周子昂  阅读(6)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3