2017-03-09 23 views
0

(Xlib/XCBを使用してバイパスするために)要求を直接Xサーバーに送信するためにソケットをオープンしています。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()は、要求されたバイト数全体を送信することを保証しません。その戻り値は実際に何回送信されたかを示しています。短い書き込みの場合は残りのバイトを送信するためにwrite()を1回以上追加する必要があります。

ストリームのソケットファイル記述子をfdopen()でストリームにラップし、ストリームI/O関数を使用して、Cライブラリにそのほとんどを入れることができます。その場合、setvbuf()でバッファリングの詳細を設定できます。

+0

私は 'fwrite'で' fdopen'を使ってみたところ、ずっと遅かったです。私は '書き込み'に固執すると思います。ありがとう! –

+1

@étale-cohomology - ジョンの答えは非常に簡潔であり、重要なアドバイスが含まれています。彼が指摘しているように、 'write'は**いくつかの**データだけを送るかもしれませんが、それはすべてではありません。場合によっては、より遅くなる可能性があります。私は[facil.io](http://facil.io)のロックでユーザランドバッファを実装しましたが、それは明らかに遅いですが、予期せぬデータ損失よりも優れています。 – Myst

関連する問題