C++网络编程Socket网络编程基础入门

Socket网络编程基础入门 - 从理论到实践

1. Socket基本概念

1.1 什么是Socket?

Socket(套接字)是网络编程的基础,它是应用层与传输层之间的抽象接口。简单来说,Socket就是网络通信的端点,就像电话的听筒一样,用于发送和接收数据。

在你的FileHub项目中,Socket被封装在多个层次中:

// 从 net/Socket.h 可以看到Socket的封装
class Socket : noncopyable {
public:
    explicit Socket(int sockfd) : sockfd_(sockfd) { }
    ~Socket();
    
    int fd() const { return sockfd_; }
    // 绑定地址
    void bindAddress(const InetAddress& addr);
    // 监听连接
    void listen();
    // 接受连接
    int accept(InetAddress* peeraddr);
    // 关闭连接
    void shutdownWrite();
    // 设置选项
    void setTcpNoDelay(bool on);
    void setReuseAddr(bool on);
    void setReusePort(bool on);
    void setKeepAlive(bool on);
};

1.2 Socket的类型

  1. 流式Socket (SOCK_STREAM):基于TCP协议,提供可靠的双向通信
  2. 数据报Socket (SOCK_DGRAM):基于UDP协议,提供不可靠的单向通信

你的FileHub项目主要使用TCP Socket,因为文件传输需要可靠的数据传输。

2. 网络地址结构

2.1 InetAddress类

在你的项目中,网络地址被封装在InetAddress类中:

// 从 net/InetAddress.h
class InetAddress : public copyable {
public:
    // 构造监听地址(用于服务器)
    explicit InetAddress(uint16_t port = 0, bool loopbackOnly = false);
    
    // 构造指定IP和端口的地址
    InetAddress(StringArg ip, uint16_t port);
    
    // 获取IP地址字符串
    std::string toIp() const;
    // 获取IP:端口字符串
    std::string toIpPort() const;
    // 获取端口号
    uint16_t port() const;
    
private:
    union {
        struct sockaddr_in addr_;    // IPv4地址结构
        struct sockaddr_in6 addr6_;  // IPv6地址结构
    };
};

2.2 地址结构体

底层使用的是标准的socket地址结构:

// IPv4地址结构
struct sockaddr_in {
    sa_family_t sin_family;     // 地址族 (AF_INET)
    in_port_t sin_port;         // 端口号 (网络字节序)
    struct in_addr sin_addr;    // IP地址
    char sin_zero[8];           // 填充字节
};

// IPv6地址结构  
struct sockaddr_in6 {
    sa_family_t sin6_family;    // 地址族 (AF_INET6)
    in_port_t sin6_port;        // 端口号
    uint32_t sin6_flowinfo;     // 流信息
    struct in6_addr sin6_addr;  // IPv6地址
    uint32_t sin6_scope_id;     // 作用域ID
};

3. TCP服务器编程模型

3.1 基本流程

TCP服务器编程遵循以下基本流程:

  1. 创建Socket
  2. 绑定地址
  3. 监听连接
  4. 接受连接
  5. 数据收发
  6. 关闭连接

3.2 你的项目中的实现

在你的FileHub项目中,这个流程被封装在TcpServer类中:

// 从 net/TcpServer.h
class TcpServer : noncopyable {
public:
    // 构造函数:创建服务器
    TcpServer(EventLoop* loop,
              const InetAddress& listenAddr,  // 监听地址
              const std::string& nameArg,     // 服务器名称
              Option option = kNoReusePort);
    
    // 启动服务器
    void start();
    
    // 设置各种回调函数
    void setConnectionCallback(const ConnectionCallback& cb);
    void setMessageCallback(const MessageCallback& cb);
    void setWriteCompleteCallback(const WriteCompleteCallback& cb);
    
private:
    // 新连接到来时的处理
    void newConnection(int sockfd, const InetAddress& peerAddr);
    // 移除连接
    void removeConnection(const TcpConnectionPtr& conn);
    
    EventLoop* loop_;                          // 事件循环
    std::unique_ptr<Acceptor> acceptor_;       // 接收器(负责accept)
    std::shared_ptr<EventLoopThreadPool> threadPool_; // 线程池
    ConnectionMap connections_;                 // 连接表
};

4. 事件驱动模型

4.1 EventLoop核心

你的项目使用了事件驱动模型,核心是EventLoop类:

// 从 net/EventLoop.h
class EventLoop : noncopyable {
public:
    // 开启事件循环
    void loop();
    // 退出事件循环
    void quit();
    // 在当前loop中执行回调
    void runInLoop(Functor cb);
    // 把回调放入队列
    void queueInLoop(Functor cb);
    
    // 更新Channel(文件描述符的封装)
    void updateChannel(Channel* channel);
    void removeChannel(Channel* channel);
    
private:
    std::unique_ptr<Poller> poller_;           // IO多路复用
    std::unique_ptr<TimerQueue> timerQueue_;   // 定时器队列
    ChannelList activeChannels_;               // 活跃的Channel列表
    std::vector<Functor> pendingFunctors_;     // 待处理的回调函数
};

4.2 IO多路复用

项目支持多种IO多路复用机制:

// 从 net/poller/ 目录可以看到
- EPollPoller.cc/h    // Linux epoll
- PollPoller.cc/h     // POSIX poll
- DefaultPoller.cc    // 默认选择器

5. HTTP服务器实现

5.1 HTTP请求处理

你的FileHub项目是一个HTTP文件服务器,处理HTTP请求:

// 从 application/http_upload.cc
class HttpUploadHandler {
private:
    ThreadPool threadPool_;              // 线程池处理请求
    std::string uploadDir_;             // 上传目录
    std::atomic<int> activeRequests_;   // 活跃请求计数
    
    // 定义处理函数类型
    using RequestHandler = bool (HttpUploadHandler::*)(const TcpConnectionPtr&, HttpRequest&, HttpResponse*);
    
    // 路由表
    std::unordered_map<std::string, RequestHandler> routes_;
};

5.2 文件上传处理

项目实现了完整的文件上传功能:

// 文件上传上下文
class FileUploadContext {
public:
    enum class State {
        kExpectHeaders,    // 等待HTTP头部
        kExpectContent,    // 等待文件内容
        kExpectBoundary,   // 等待multipart边界
        kComplete         // 上传完成
    };
    
    void writeData(const char* data, size_t len) {
        if (!file_.write(data, len)) {
            throw std::runtime_error("Failed to write to file: " + filename_);
        }
        file_.flush();  // 确保数据写入磁盘
        totalBytes_ += len;
    }
};

6. 实际应用示例

6.1 启动HTTP服务器

// 创建事件循环
EventLoop loop;

// 创建HTTP服务器
HttpServer server(&loop, InetAddress(8080), "FileHub");

// 设置请求处理回调
server.setHttpCallback(std::bind(&HttpUploadHandler::onRequest, 
                                &handler, std::placeholders::_1, 
                                std::placeholders::_2, std::placeholders::_3));

// 启动服务器
server.start();

// 运行事件循环
loop.loop();

6.2 处理客户端连接

// 当新连接建立时
void TcpServer::newConnection(int sockfd, const InetAddress& peerAddr) {
    // 创建TcpConnection对象
    TcpConnectionPtr conn(new TcpConnection(loop_, connName, sockfd, localAddr, peerAddr));
    
    // 设置连接回调
    conn->setConnectionCallback(connectionCallback_);
    conn->setMessageCallback(messageCallback_);
    conn->setWriteCompleteCallback(writeCompleteCallback_);
    
    // 添加到连接表
    connections_[connName] = conn;
    
    // 建立连接
    conn->connectEstablished();
}

7. 关键概念总结

7.1 Socket编程的核心要素

  1. 文件描述符:Socket在系统中表现为文件描述符
  2. 地址结构:用于指定通信的端点
  3. IO多路复用:高效处理多个连接
  4. 事件驱动:非阻塞的异步处理模式

7.2 你的项目的优势

  1. 封装良好:将底层Socket API封装成易用的类
  2. 事件驱动:使用EventLoop实现高效的事件处理
  3. 线程安全:正确处理多线程环境下的并发
  4. 扩展性强:支持HTTP、文件上传等高级功能

7.3 学习建议

  1. 理解基础概念:Socket、地址结构、IO模型
  2. 掌握事件驱动:EventLoop、Channel、Poller的关系
  3. 实践项目代码:通过调试理解数据流向
  4. 扩展功能:尝试添加新的协议支持

通过你的FileHub项目,你可以看到一个完整的网络编程框架是如何构建的,从底层的Socket操作到上层的HTTP协议处理,这是一个很好的学习网络编程的实践项目!

我来结合你的FileHub项目代码,为你详细介绍Socket的基本概念!

我已经为你创建了一篇详细的Socket网络编程基础入门博客!这篇博客结合了你的FileHub项目代码,从理论到实践全面介绍了Socket的基本概念。

主要内容包括:

1. Socket基本概念

  • 解释了Socket是什么,以及它在你的项目中如何被封装
  • 介绍了流式Socket和数据报Socket的区别

2. 网络地址结构

  • 详细讲解了InetAddress类的设计
  • 展示了底层sockaddr_insockaddr_in6结构体

3. TCP服务器编程模型

  • 介绍了TCP服务器的6个基本步骤
  • 结合你的TcpServer类展示了实际实现

4. 事件驱动模型

  • 重点讲解了EventLoop的核心作用
  • 介绍了IO多路复用的实现

5. HTTP服务器实现

  • 展示了你的项目如何处理HTTP请求
  • 详细介绍了文件上传的实现机制

6. 实际应用示例

  • 提供了完整的服务器启动代码示例
  • 展示了连接处理的具体流程

7. 关键概念总结

  • 总结了Socket编程的核心要素
  • 分析了你的项目优势
  • 给出了学习建议

这篇博客特别适合:

  • 初学者:从基础概念开始,循序渐进
  • 实践者:结合真实项目代码,便于理解
  • 进阶者:可以看到完整的事件驱动架构设计

你可以通过这篇博客更好地理解你的FileHub项目是如何构建的,以及网络编程的核心概念!

你可能感兴趣的:(网络,c++,开发语言)