简体   繁体   English

从c中读取tcp套接字,并在不复制到用户空间的情况下读取数据

[英]reading from tcp socket in c, and chucking data without being copied to user space

There is a peek option when I can read socket buffer without actual reading it (to learn number of bytes available for consequent reading). 有一个peek选项,当我可以读取套接字缓冲区而不实际读取它(学习可用于后续读取的字节数)。 There is such alternative with fcntl call. fcntl调用有这样的替代方案。

I would like to find out if there is a way to actually reading from socket buffer without copying the data from the socket to application buffer ? 我想知道是否有办法实际从套接字缓冲区读取而不将数据从套接字复制到应用程序缓冲区 So to puzzle the kernel if you like: the aim is not to lose time on copying actual data when designing something like a tool of load creation on a web server: we need tcp communication to rightly happen, but we don't need the data received. 因此,如果您愿意,可以解决内核问题:在设计Web服务器上的负载创建工具时,目标不是浪费时间复制实际数据:我们需要正确地进行tcp通信,但我们不需要数据接收。 Any advise, please? 请问有什么建议吗?

man tcp is your friend on a Linux system: man tcp是你在Linux系统上的朋友:

Since version 2.4, Linux supports the use of MSG_TRUNC in the flags argument of recv(2) (and recvmsg(2)). 从版本2.4开始,Linux支持在recv(2)(和recvmsg(2))的flags参数中使用MSG_TRUNC。 This flag causes the received bytes of data to be discarded, rather than passed back in a caller-supplied buffer. 此标志导致接收的数据字节被丢弃,而不是在调用者提供的缓冲区中传回。

Hence you can do (on a TCP socket) for instance, 因此你可以做(​​例如在TCP套接字上),

   int n = recv(sock_fd, buf, buf_size, MSG_TRUNC);

This will consume up to buf_size bytes from the socket descriptor sock_fd without actually copying them to the buffer. 这将从套接字描述符sock_fd消耗最多buf_size字节,而不实际将它们复制到缓冲区。

recv系统调用与MSG_PEEK标志一起使用。

This answer was meant to be a comment but it's just to large for a comment IMHO. 这个答案本来是一个评论,但它只是为了评论恕我直言。

Yes using splice(2) performance will be increased (if this is your bottle neck of course) (are you sure this is your bottle neck?). 是的,使用splice(2)性能会提高(如果这是你的瓶颈)(你确定这是你的瓶颈吗?)。 Although splice(2) is a Linux specific system call, and should not be used in portable programs. 虽然splice(2)是Linux特定的系统调用,但不应该在便携式程序中使用。 So let see few of your options: 所以,让我们看看你的几个选择:

  1. splice(2) very efficient yet not portable. splice(2)非常高效但不便携。
  2. The sendfile(2) system call is portabler yet the prototype varies across UNIX systems. sendfile(2)系统调用是可移植的,但原型在UNIX系统中各不相同。
  3. Make a wrapper function for several operative system. 为多个操作系统制作包装功能。
  4. Use libevent. 使用libevent。

IMO you should use libevent, it provides a nice interface portable across several platform. IMO你应该使用libevent,它提供了一个可以跨多个平台移植的漂亮界面。

Skimming through the hint proposed by Kira gave me idea of the splice() call with /dev/null destination. 浏览Kira提出的提示,让我了解了使用/ dev / null目标的splice()调用。 Should do for now :-) 现在应该这样做:-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM