Previous: 準備
Up: Xウィンドウ実習
第10回
Xのネットワーク機能
Next: 補足(ビットマップ・エディターの使い方)
Previous Page: 準備
Next Page: 補足(ビットマップ・エディターの使い方)
Xウィンドウでは、ネットワークを使うプログラムを
非常に簡単に開発できます。
実用的な例として、前に作ったペイントツール(paint1.c)を
改良した簡単な通信ツールを作ってみましょう。
ネットワークを利用するのに必要な手続きは、他のマシン上で動いている
サーバーを呼び出すことだけです。サーバーを呼び出す命令は
他のマシンであってもすでに勉強した XOpenDisplay() を使います。
この関数の引数に相手のディスプレイ名を与えて、
サーバーとの接続を開始してください。
次のプログラムは、自分の画面と同じ内容の表示を
他の人のディスプレイにも送ります。
自分と相手の両方のディスプレイをオープンするために
XOpenDisplay() が2回呼び出されている点に注目してください。
ウィンドウやピクスマップ、GCなどのデータも
二重に用意しなくてはいけません。
相手のマシン名は、プログラムを実行する時に
コマンドラインから与えることにします。
(ソース・ファイル名は xtalk.c としてください。)
xtalk.c
#include<stdio.h> #include<X11/Xlib.h>main( int argc, char **argv ) { Display *dsp; Window frame; Window canvas, command; Window quit, clear; GC gc; XEvent eve;
Display *dsp2; /* 相手のディスプレイ構造体の宣言 */ Window canvas2; /* 相手のウィンドウ構造体の宣言 */ GC gc2; /* 相手のGC構造体の宣言 */
int x1,y1,x2,y2;
char *server_name; /* 相手のディスプレイ名を記憶する文字列 */
if( argc == 2 ) /* コマンドラインからホスト名の指定があった */ { server_name = (char *)malloc( strlen(argv[1])+3 ); /* 文字列のメモリー確保 */ sprintf( server_name, "%s:0", argv[1] ); /* ディスプレイ名に変換 */ } else /* 指定のない時は自分の画面に表示 */ { server_name = NULL; }
dsp = XOpenDisplay( NULL ); /* 自分のマシンのサーバーと接続 */
dsp2 = XOpenDisplay( server_name ); /* 相手のサーバーとも接続 */ if( dsp2 == NULL ) /* 相手のホストが正しくオープンできたか? */ { printf( "ホスト名の指定が正しくありません\n" ); exit(0); }
frame = XCreateSimpleWindow( dsp, DefaultRootWindow(dsp), 0, 0, 600, 400, 1, BlackPixel(dsp,0), BlackPixel(dsp,0) ); canvas = XCreateSimpleWindow( dsp, frame, 5, 5, 555, 355, 0, BlackPixel(dsp,0), WhitePixel(dsp,0) ); command = XCreateSimpleWindow( dsp, frame, 565, 265, 30, 95, 0, BlackPixel(dsp,0), WhitePixel(dsp,0) ); quit = XCreateSimpleWindow( dsp, command, 2, 5, 24, 24, 1, BlackPixel(dsp,0), WhitePixel(dsp,0) ); clear = XCreateSimpleWindow( dsp, command, 2, 35, 24, 24, 1, BlackPixel(dsp,0), WhitePixel(dsp,0) );
/* 相手のウィンドウの生成 */ canvas2 = XCreateSimpleWindow( dsp2, DefaultRootWindow(dsp2), 0, 0, 555, 355, 0, BlackPixel(dsp2,0), WhitePixel(dsp2,0) );
gc = XCreateGC( dsp, canvas, NULL, NULL ); XSetForeground( dsp, gc, BlackPixel(dsp,0) ); gc2 = XCreateGC( dsp2, canvas2, NULL, NULL ); /* 相手のGCの生成 */ XSetForeground( dsp2, gc2, BlackPixel(dsp2,0) );
XSelectInput( dsp, canvas, ButtonPressMask | Button1MotionMask ); XSelectInput( dsp, quit, ButtonPressMask | ExposureMask ); XSelectInput( dsp, clear, ButtonPressMask | ExposureMask );
XStoreName( dsp, frame, "送信ウィンドウ" ); XStoreName( dsp2, canvas2, "受信ウィンドウ" ); /* 相手のタイトルの設定 */
XMapWindow( dsp, frame ); XMapSubwindows( dsp, frame ); XMapSubwindows( dsp, command );
/* 相手のウィンドウの表示 */ XMapWindow( dsp2, canvas2 );
XFlush( dsp ); XFlush( dsp2 );
while( True ) { XNextEvent( dsp, &eve );
if( eve.xany.window == canvas ) { switch( eve.type ) { case ButtonPress: switch( eve.xbutton.button ) { case 1: x1=eve.xbutton.x; y1=eve.xbutton.y; break; default: break; } break; case MotionNotify: x2=eve.xbutton.x; y2=eve.xbutton.y; XDrawLine( dsp, canvas, gc, x1, y1, x2, y2 ); XFlush(dsp); XDrawLine( dsp2, canvas2, gc2, x1, y1, x2, y2 ); /* 送信 */ XFlush(dsp2); x1=x2; y1=y2; break; default: break; } continue; }
if( eve.xany.window == clear ) { switch( eve.type ) { case ButtonPress: XClearWindow( dsp, canvas ); XFlush(dsp); XClearWindow( dsp2, canvas2 ); /* 相手のキャンバスのクリア */ XFlush(dsp2); break; case Expose: XDrawString( dsp, clear, gc, 4, 16, "Cls", 3 ); break; default: break; } continue; }
if( eve.xany.window == quit ) { switch( eve.type ) { case ButtonPress: XCloseDisplay( dsp ); XCloseDisplay( dsp2 );/* 相手のディスプレイのクローズ */ exit(0); case Expose: XDrawString( dsp, quit, gc, 2, 16, "Quit", 4 ); break; default: break; } continue; } } }
プログラム xtalk.c をコンパイルして実行してみましょう。
このプログラムでは、通信したい相手のマシン名だけで
指定できるようにしておきました。
ipca3, ipcd2, ipcf1 などのように実行してください。
a.out ipca7