繁体   English   中英

UNIX套接字的缓冲写入?

[英]Buffered writes for UNIX sockets?

我正在打开一个套接字,将请求直接发送到X服务器(以使用Xlib / XCB绕过)。

#define X11_OP_REQ_CREATE_WINDOW  0x01
#define X11_OP_REQ_MAP_WINDOW     0x08
#define X11_OP_REQ_CREATE_PIX     0x35
#define X11_OP_REQ_CREATE_GC      0x37
#define X11_OP_REQ_PUT_IMG        0x48

...

  struct sockaddr_un serv_addr = {0};
  int socketfd = socket(AF_UNIX, SOCK_STREAM, 0);  // Create the socket!
  serv_addr.sun_family = AF_UNIX;
  strcopy(serv_addr.sun_path, "/tmp/.X11-unix/X0", 0);
  int srv_len = sizeof(struct sockaddr_un);
  connect(socketfd,(struct sockaddr*)&serv_addr, sizeof(serv_addr));

不过,我必须做一堆write() ,而且我知道对于文件来说,由于缓冲,它可能比fwrite慢很多,因为syscalls很昂贵。 是否有与套接字兼容的等效功能? 甚至可以使用套接字进行缓冲的IO吗? (不要fwrite需要FILE*流,而我所拥有的只是一个描述符。)

这是一个发送此类请求(使用write )的函数示例。

void x11_put_img(int socketfd, struct x11_connection* conn, uint8 format, uint32 target, uint32 gc, uint16 w, uint16 h, uint16 x, uint16 y, uint8 depth, uint32* data){
    uint32 packet[6];
    uint16 length = ((w*h)) + 6;

    packet[0] = X11_OP_REQ_PUT_IMG | format<<8 | length<<16;
    packet[1] = target;
    packet[2] = gc;
    packet[3] = w | h<<16;
    packet[4] = x | y<<16;
    packet[5] = depth<<8;

    write(socketfd, packet, 24);
    write(socketfd, data, (w*h)*4);

    return;
}

(为简便起见,没有错误检查。)

正在执行缓冲写入,尽管有点不正确。 例如,当您打电话时,

    write(socketfd, packet, 24);

你觉得packet是什么?

现在,您可以创建一个更大的缓冲区,例如unsigned char buffer[4096] ,然后将输出memcpy()放入其中,并最终一次write()更大的数据块。 但是,这仅在某种程度上是有意义的,因为如果您还需要接收您发送的消息的响应 ,那么除了在消息边界(除非消息过长)之外,中断传输没有任何好处,这会使您的发送变得复杂代码以在发送之前缓冲多个消息。

但是请注意, write()不能保证发送请求的全部字节数。 它的返回值告诉您它实际发送了多少,如果发生短写,您可能需要再调用一次write()来发送其余字节。

您确实可以选择通过将套接字文件描述符通过fdopen()包装在流中并使用流I / O函数,将大部分内容放在C库中。 在这种情况下,您可以通过setvbuf()配置缓冲详细信息。

暂无
暂无

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

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