socket通信中的accept函数

int connfd = ::accept(m_sockfd, (struct sockaddr*)&addr, &addr_len);

你已经意识到这里有的是传入参数,有的是传出参数,说明你在认真理解系统调用的行为 —— 这是系统编程非常重要的能力。


✅ 先回顾一下 accept() 的函数原型:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

✅ 参数逐个讲清楚:

参数名 类型 方向 说明
sockfd int 输入参数 监听 socket 的文件描述符,即 m_sockfd,必须已 listen()
addr struct sockaddr* 输出参数 用于返回客户端的地址信息(写入数据)
addrlen socklen_t* 输入/输出参数 初始传入 addr 的大小,返回时被修改为实际使用的大小

✅ 一句话总结每个参数作用

m_sockfd(传入参数)

  • 这是你前面用 socket() + bind() + listen() 得到的监听 socket。

  • 告诉操作系统:“我现在要从这个 socket 上接收一个连接请求”。


(struct sockaddr*)&addr(传出参数)

  • 这是输出用的结构体,系统会在连接建立后,把客户端的 IP/端口信息写入到 addr 里。

  • 所以你需要提前定义这个变量(如 sockaddr_in addr;),传指针进去。


&addr_len(传入 + 传出)

  • 你一开始要告诉操作系统:“这个地址结构的大小是多大”(通常是 sizeof(addr))。

  • 系统会在调用结束时修改它的值为实际写入的字节数(即客户端地址信息长度)。

  • 这是典型的 C 接口“in/out”双向参数。


✅ 图示理解参数传递方向:

调用前:
  m_sockfd → 已监听的 socket
  addr     → 空结构体,等着系统写入客户端地址
  addrlen  → sizeof(addr)

调用后(成功):
  connfd   → 新的连接 socket
  addr     → 填好了客户端 IP/端口
  addrlen  → 系统写回实际地址长度

✅ 常见错误提醒:

  1. ❌ 没有给 addr_len 设置初值:

    socklen_t addr_len;
    accept(sockfd, (sockaddr*)&addr, &addr_len); // ❌ 未初始化,可能失败
    
  2. ✅ 正确做法是:

    socklen_t addr_len = sizeof(addr);
    

✅ 补充:返回值 connfd

  • 它是新的 socket fd,专门用于与当前这个客户端通信

  • m_sockfd 不同(后者还在继续监听新的连接)


✅ 总结重点:

参数 输入 / 输出 作用
m_sockfd 输入 哪个监听 socket 来 accept
addr 输出 客户端地址将被写到这里
addr_len 输入 + 输出 告诉系统结构体多大、系统写入实际使用大小

你可能感兴趣的:(c++基础知识,C++,网络,服务器,linux)