1

有几个套接字问题,找不到明确的是或否,所以如果是转发,请提前道歉:) 平台是 Linux 2.6.30,C++ 应用程序。对网络还是很陌生,要跟上速度。

  1. 套接字 API 线程安全吗?例如,如果我在不使用互斥锁的情况下从多个线程进行发送,或者我必须通过使用自己的互斥锁来确保这一点?

  2. 轮询/选择以检查我的发送是否会阻塞然后进行发送,而不是仅进行发送并让发送 API 内部排队处理发送是否更好?如果线程无论如何都会阻塞(如果我不使用超时,也就是说),我真的不明白为什么需要轮询然后发送。

  3. Linux中默认情况下套接字是零副本,还是涉及副本?如果有副本,是否有大小限制(不是在 API 方面,而是在粒度方面)?如果答案是内核确实进行了复制,是否存在零复制套接字?

  4. 如果我必须在两台机器之间进行通信,我会假设多个套接字会比单个套接字更好地利用带宽。这是一个正确的假设吗?在两台常规 Linux 机器之间使用完整 BW 的最佳方式是什么?

5.你最喜欢测量接口当前带宽使用情况的工具是什么?这可能只是更多的偏好,我查看了 iptraf 等,但想看看其他人使用什么和最喜欢什么。

4

2 回答 2

3
  1. 套接字 API 在每个套接字的基础上绝对是线程安全的……也就是说,只要任何给定的套接字仅由一个线程访问,其他线程就可以同时访问其他套接字而不会出现任何问题。让多个线程同时访问同一个套接字可能是“线程安全”的,也可能不是“线程安全的”(对于线程安全的某些定义),但无论如何都不建议这样做,因为结果行为不容易预测。(例如,两个线程大约同时在同一个套接字上调用 recv(),哪个线程将从传入的 TCP 流中获取哪些字节?只有上帝知道)

  2. 如果您正在使用阻塞 I/O,那么在调用 send() 之前使用 poll/select() 检查并不是非常有用,因为即使 select() 表明您在传出缓冲区中有空间,您也可能会阻塞在 send()反正。(例如,如果缓冲区中有 32 个字节的空间,然后您尝试发送 64 个字节,则 send() 将阻塞)。select() 和 poll() 与非阻塞 I/O 结合使用更有用。

  3. 我不太确定 Linux 套接字中的零拷贝状态,但Wikipedia 文章似乎暗示 Linux 仅在使用 sendfile()、sendfile64() 或 splice() 调用时才进行零拷贝。考虑到现代 CPU,我怀疑它是否有那么重要——除了最高性能的程序之外,所有程序都将有大量 CPU 周期可用于复制网络数据;网络接口本身的速度将成为瓶颈。

  4. 多个套接字不会比单个套接字为您提供更好的带宽利用率;如果您足够快地通过它泵送数据,则单个套接字很容易使网络连接饱和。特别是多个 TCP 连接通常会给您带来比单个 TCP 连接更差的带宽利用率,因为每个 TCP 连接都会产生自己的传输开销,更糟糕的是,多个 TCP 连接将争夺带宽,并在某些时候开始导致彼此丢弃数据包,他们将通过降低发送速率来响应,以减少拥塞。

  5. 我无法为 Linux 回答这个问题;在 MacOS/X 活动监视器下将显示网络带宽使用情况。

于 2012-04-30T04:34:24.873 回答
1

Jeremy 的第 3 点有些不准确。随着多个高速网络接口和大量数据的移动,零拷贝变得更加重要。在内存中复制缓冲区所花费的时间会影响吞吐量和延迟。异步 IO 和分散/聚集支持对于高速网络系统至关重要。

于 2012-08-20T16:07:15.373 回答