2017-03-09 53 views
0

我打开一个套接字将请求直接发送到X服务器(绕过使用Xlib/XCB)。针对UNIX套接字的缓冲写入?

#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,虽然,我知道,这个文件可能是慢了很多比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; 
} 

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

+0

不知道你是怎么想的。通常,如果您通过套接字发送某个内容,则需要在发送下一个命令之前进行回复。通过缓冲写入,您还可以缓冲读取和某种消息队列。不知道这是否真的值得开销。 – Olaf

+0

[writev](http://man7.org/linux/man-pages/man2/readv.2.html)? – rici

回答

3

做着缓冲写道,虽然有点不正确。当你打电话时,例如,

write(socketfd, packet, 24); 

你认为packet是什么?

现在,您可以创建一个更大的缓冲区,例如unsigned char buffer[4096],然后memcpy()将其输出到最终的数据块中,并最终创建更大的数据块。然而,这只适用于某一点,因为如果您还需要接收响应以发送您发送的消息,则除了在消息边界以外分解传输没有任何优势(除非消息太长),它会使您的代码在发送前缓冲多个消息。

但请注意,write()不保证发送请求的全部字节数。它的返回值告诉你它实际发送了多少,并且在短写的情况下,你可能需要调用write()一个或多个额外的时间来发送其余的字节。

你确实有把C库大部分由VIA fdopen()包裹在一个流套接字文件描述符,并使用流I/O功能的选项。在这种情况下,您可以通过setvbuf()配置缓冲细节。

+0

我只是试着'fdopen'与'fwrite'并且慢得多。我想我会坚持'写'。谢谢! –

+1

@étale-cohomology - 约翰的答案非常简洁,包含重要的建议。正如他指出的那样,'write'可能只会发送**一些**数据(但不是全部) - 这是您在本地测试时不太可能遇到的情况。在某些情况下,速度较慢可能会更安全......我实现了一个锁定[facil.io](http://facil.io)的用户缓冲区,它显然比较慢,但它比意外的数据丢失要好。 – Myst