打造自己的 C++ Socket 服务器:手把手教程

打印 上一主题 下一主题

主题 883|帖子 883|积分 2649

Socket 服务器技术文档

1. 概述

本文档描述了一个基于 C++ 的简单 TCP socket 服务器的实现和用法。该服务器监听指定的端口,接受客户端毗连,读取客户端发送的消息,并向客户端发送一个固定的响应消息。
2. 情况要求



  • C++ 编译器,支持 C++11 或更高版本
  • POSIX 兼容操纵体系
  • 支持 POSIX socket API 的库
3. 编译和运行


6. 后续改进


  • 将服务器代码生存为一个名为 server.cpp 的文件。
  • 利用以下下令编译代码:
    1. g++ server.cpp -o server
    复制代码
  • 运行服务器:
    1. ./server
    复制代码
    4. 服务器实现

    4.1 头文件

    1. #include <iostream>
    2. #include <cstring>
    3. #include <sys/socket.h>
    4. #include <netinet/in.h>
    5. #include <unistd.h>
    复制代码
    这些头文件分别用于输入输出流、字符串操纵、socket 编程、网络地点布局和 UNIX 标准函数。
    4.2 定义端口号和缓冲区巨细

    1. #define PORT 8080
    2. #define BUFFER_SIZE 1024
    复制代码
    PORT 定义了服务器监听的端口号,BUFFER_SIZE 定义了用于读取和发送数据的缓冲区巨细。
    4.3 主函数

    1. int main() {
    2.     // ...
    3. }
    复制代码
    主函数是程序的入口点,包含了服务器的主要逻辑。
    4.4 创建 socket

    1. int server_fd, new_socket;
    2. server_fd = socket(AF_INET, SOCK_STREAM, 0);
    复制代码
    创建一个 socket 文件描述符 server_fd,用于监听客户端毗连。AF_INET 表示 IPv4 地点族,SOCK_STREAM 表示 TCP 流套接字。
    4.5 绑定地点和端口

    1. struct sockaddr_in address;
    2. bind(server_fd, (struct sockaddr*)&address, sizeof(address));
    复制代码
    将 socket 绑定到本地地点和端口。
    4.6 监听毗连

    1. listen(server_fd, 3);
    复制代码
    开始监听是否有客户端毗连。第二个参数 3 表示最大毗连数。
    4.7 接受毗连

    1. new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);
    复制代码
    接受客户端的毗连,并返回一个新的 socket 文件描述符 new_socket。
    4.8 读取和发送数据

    1. read(new_socket, buffer, BUFFER_SIZE);
    2. send(new_socket, hello, strlen(hello), 0);
    复制代码
    从客户端读取数据到缓冲区,并向客户端发送固定的响应消息。
    4.9 关闭 socket

    1. close(server_fd);
    复制代码
    关闭服务器 socket,开释资源。
    5. 注意事项
  • 本示例代码没有进行错误查抄和非常处置处罚,这在实际应用中是非常紧张的。
  • 服务器只能同时处置处罚一个客户端毗连,不支持并发。
  • 服务器在发送响应消息后立即关闭毗连,不进行持续通信。
  • 添加错误查抄和非常处置处罚。
  • 利用多线程或多进程支持并发毗连。
  • 实现完备的客户端-服务器通信协议。
    1. #include <iostream>
    2. #include <cstring>
    3. #include <sys/socket.h>
    4. #include <netinet/in.h>
    5. #include <unistd.h>
    6. #define PORT 8080
    7. #define BUFFER_SIZE 1024
    8. int main() {    int server_fd, new_socket;    struct sockaddr_in address;    int opt = 1;    int addrlen = sizeof(address);    char buffer[BUFFER_SIZE] = {0};    const char* hello = "Hello from server";    // 创建 socket 文件描述符    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {        perror("socket failed");        exit(EXIT_FAILURE);    }    // 绑定 socket 到地点和端口    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);    }    // 接受客户端的毗连    if ((new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen))<0) {        perror("accept");        exit(EXIT_FAILURE);    }    // 读取数据    read(new_socket, buffer, BUFFER_SIZE);    std::cout << "Message from client: " << buffer << std::endl;    // 发送数据    send(new_socket, hello, strlen(hello), 0);    std::cout << "Hello message sent\n";    // 关闭 socket    close(server_fd);
    9.     return 0;}
    复制代码
    几个问题1.sockfd是什么?答:
    在 socket 编程中,sockfd 是一个术语,通常用于指代一个 socket 的文件描述符。在 Unix-like 体系中,险些全部的 I/O 操纵都是通过文件描述符进行的,包括网络通信。文件描述符是一个非负整数,它是内核为了高效管理已打开的文件或其他 I/O 资源(如 socket、管道、设备等)而提供的一个抽象句柄。
    当你创建一个 socket 时,体系会返回一个文件描述符,这个文件描述符就被称为 sockfd。之后,你就可以利用这个文件描述符来进行各种 socket 操纵,好比绑定地点(bind)、监听毗连(listen)、接受毗连(accept)、读取数据(read)、发送数据(write 或 send)、关闭 socket(close)等。
    比方,在下面的代码中,socket 函数创建了一个新的 socket,并返回了一个文件描述符,这个描述符被存储在变量 sockfd 中:
    1. int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    复制代码
    在这里,AF_INET 指定了地点族为 IPv4,SOCK_STREAM 指定了 socket 范例为 TCP 流套接字。如果 socket 调用成功,sockfd 将是一个有效的文件描述符,用于后续的 socket 操纵。如果调用失败,sockfd 将被设置为一个特定的错误值(通常是 -1),而且可以通过查看 errno 变量来获取失败的缘故原由。
    我们可以用一个类比来通俗易懂地解释 sockfd。
    想象一下,你的电脑是一个大型的邮局,而你想通过邮局发送和吸收信件。在邮局中,每个信箱都有一个唯一的编号,这个编号就像是文件描述符。当你创建一个 socket 时,就像是你在邮局申请了一个新的信箱,邮局会给你一个编号(即 sockfd),这样你就可以通过这个编号来发送和吸收信件了。
    当你想发送一封信时,你会把信放入对应编号的信箱中,然后邮局会帮你把信发送出去。同样地,当你创建了一个 socket 并获得了 sockfd,你就可以利用这个 sockfd 来进行网络通信,好比发送数据(send)和吸收数据(recv)。
    当你不再必要这个信箱时,你可以通知邮局回收这个信箱,这样其他人就可以利用这个编号了。在 socket 编程中,当你完成全部的通信使命后,你必要关闭 socket,开释 sockfd,这样体系就可以重新利用这个编号了。
    以是,sockfd 就像是邮局信箱的编号,它资助你管理和操纵网络通信。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

惊雷无声

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表