C- unix插座的缓冲写作



我正在打开一个插座,直接将请求发送到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() s,我知道,由于Syscalls很昂贵,因此由于缓冲而要比fwrite慢得多。是否有等效函数可与插座一起使用?是否有可能用插座进行缓冲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;
}

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

you 做缓冲的写入,尽管有些不正确。例如,当您致电时,

    write(socketfd, packet, 24);

您认为packet是什么?

现在,您可以创建一个较大的缓冲区,例如unsigned char buffer[4096],然后memcpy()输出到其中,最终一次write()较大的数据。但是,这只有一定程度才有意义,因为如果您还需要接收到发送消息的响应,则除了在消息边界处以外的传输没有其他优势(除非消息非常长),并且在发送之前会使您的代码复杂到多个消息。

但是,请注意,write()不保证发送所请求的总字节数。它的返回值告诉您它实际发送了多少,如果短写作,您可能需要致电write()一个或多个额外的时间以发送其余字节。

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

最新更新