• ベストアンサー

read関数をノンブロッキングで実行する(c言語)

read関数をノンブロッキングで実行する方法がわかりません。 O_NONBLOCKを使用して、readがEAGAINを返したらどうのこうのと、マニュアルにありましたが その辺の一連をどのように書けばよいのかを教えてください。 unix上でTCPでやりたいです。

質問者が選んだベストアンサー

  • ベストアンサー
  • chirubou
  • ベストアンサー率37% (189/502)
回答No.3

No.2 です。間違えました。No.2 は TCP のバッファリングを無効にする(バンド幅は小さくなるが、遅延が減る)ものでした。正しくは、以下の関数を fd に適用してください。 int set_nonblock_mode( int fd ) { return( fcntl( fd, F_SETFL, O_NONBLOCK ) ); }

taurus4_ikeda
質問者

お礼

ありがとうございました。ノンブロッキングできました。

その他の回答 (2)

  • chirubou
  • ベストアンサー率37% (189/502)
回答No.2

TCP のソケット(fd)に対して、以下の関数を呼べば OK です。inlcude の指定と、エラー処理は適当に書いてください。このコードは Linux で動作確認済みです。 void set_tcp_nodelay( int fd ) { struct protoent *protoent; int tmp; if( ( protoent = getprotobyname ("tcp") ) == NULL ) return; tmp = 1; (void) setsockopt( fd, protoent->p_proto, TCP_NODELAY, (char*) &tmp, sizeof(int) ); }

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.1

tcpの例文は手間がかかるので、ttyの例を書きます。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- #include <stdio.h> #include <errno.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> int main(void) { char buf[BUFSIZ]; int fd, n; fd = open("/dev/tty", O_NONBLOCK); while (1) { sleep(1); n = read(fd, buf, BUFSIZ); if (n < 0) { if (errno == EAGAIN) { fprintf(stderr, "No input\n"); continue; } else { perror("I/O error"); return errno; } } else { buf[n] = 0; printf("read = %s", buf); } } return 0; }

関連するQ&A

  • C言語のread関数に関するファイルディスクリプタ

    C言語のread関数に関するファイルディスクリプタについて質問です。 open関数から得られたファイルディスクリプタを、一般的には変数(例:fd)に代入して、fdをread関数や、write関数の第1引数として用いるんですが、ファイルディスクリプタは数値のはずなので、それを引数として用いてもどうやってそこからパス情報を得ることが出きるのかが分かりません。 例えば以下のような場合です。 ****** 省略 fd = open("/home/XXX/YYY", O_RDONLY); read(fd, buf, 10); 省略 ****** 誰か詳しい方がおりましたら、どうかご教授よろしくお願い致します。

  • 非同期関数とノンブロッキング関数について(winsock)

    こんばんわ。 VC++.NETにてコンソール上でソケットプログラミングをしています。 非同期モードとノンブロッキング関数について知りたいのですが、私は、今までTCPやUDPでsendtoやsend関数を使用してきました。しかし、非同期やノンブロッキング関数があることを知り、詳しく知りたいと思っています。 1.非同期やノンブロッキング関数はGUI作成を行う上では重要であるが、コンソール上でプログラミングを行っている場合は利用しなくてよいのでしょうか? 2.以下のWSAAsyncSelect関数の第2引数の設定がわかりません。サンプルでは、hwndに関連付けられたウィンドウがSM_EVENTメッセージを受け取りますと記述されていますが、ウィンドウを利用していないコンソールアプリでの記述方法はありますでしょうか? HWND hwnd; WSAAsyncSelect(Sock,hwnd,SM_EVENT,FD_WRITE); と記述し実行した場合、強制終了されてしまいます。 3.たとえば、送信側から送信したパケットを受信側で受信し、再度受信側から送信側へ送信する場合を考えると、 送信側で送信と受信が必要です。この場合、マルチスレッド処理が必要だと思うのですが、非同期のFD_WRITEとFD_READを使うことで、シングルスレッドで実現可能でしょうか? よろしくお願い致します。

  • シリアル通信でのread関数の戻り値

    オムロン製PLCと上位コンピュータをRS232Cで接続し、FINSコマンドを用いてシリアル通信をしようとしています。 現在作っているプログラムの流れは、 ・シリアルポート"/dev/ttyS2"のオープン   comm_fd = open("/dev/ttyS2", O_RDWR | O_NOCTTY); ・通信設定   termios構造体を設定 ・コマンドフレーム(COMMAND)を作成し、ポートに書き込む   write(comm_fd, &COMMAND, strlen(COMMAND)); ・PLCからのレスポンスを読み出す   read(comm_fd, &RESPONSE, 256); のようにしているのですが、read関数が実行されたままになってしまいます。(エラーコードも返ってこない状態です) readの戻り値が-1ならポートにアクセスできていないとわかるのですが… ためしにcomm_fdと違う値をread関数に入れてみたところ(read(6, &RESPONSE, 256)、戻り値は-1となりました。 これはどういう状態になってしまっているのでしょうか? わかりにくい質問で申し訳ありません。

  • C言語でチャットプログラミングを・・・

    C言語(unix環境)でチャットプログラミングを作りたいのですが、まずは、TCP/IPによるマルチクライアントで簡単なメッセージのやりとりができるプログラムを練習として作りたいと考えています。 そこでサーバにクライアントからメッセージが届いた時点で全クライアントにメッセージを送信(write)し、逐次更新されるようにしたいのですが、クライアント側で常にread関数を呼び出すのは非常に不格好だし、メッセージを入力するといった他の処理ができなくなると思うのです。 何か方法はありますでしょうか? なにぶんネットワークプログラミングは始めたばかりですので初心者向けの解説をお願いします。

  • C言語で、文字とか入力されなくても実行を続けたい

    現在簡単なゲームをunix系のOSのC言語でつくってますが なにも入力されなくても停止せず実行を続けられる getcharのような関数はないのでしょうか? windows系のOSにはcons.hヘッダーあたりに そんな関数あったような気がするのですが。。。 普通のgetcharだと、文字が入力されるまで(enter押されるまで) そこで実行が一時中断されてしまい リアルタイムで動くプログラムができないのですが。。。

  • ソケット通信内 read関数について

    現在C言語にソケット通信を作成しているのですが、read関数内の作成でつまずいています。 ご存知でしたら教えてください。 自分なりに調べた結果read関数の戻り値は受信した バイト数、毎回指定サイズ受け取るとは限らないと いうことでした。 そこでread関数を無限ループで回し 指定サイズ受信したら、ループを抜ける使用にしたのですが、受信バイトが0だった場合はどうすればよいのでしょか? よくサンプルなどでは、0だったらエラーと判断し、すかさずbreakしているのですが、一度でも0バイトを受信すると、それ以降は1バイト以上受信出来ないものなのでしょうか? もし出来ないのなら一度でも0を受信したら、breakしようと思っています。 出来るのでしたら、タイマー設定をし、指定受信バイトに満たなくても一定時間が過ぎたらループから抜ける使用にしたいと考えています。 そのほか良い方法があれば教えてください。 分かりずらい説明になってしまいましたが、宜しくお願い致します。

  • c言語の実行が分かりません

    C言語のプログラムを実行させる方法が分かりません。 unixでC言語を以下の手順で学習しています。 1 emacs上でファイル名.cというソースファイルを作成。 2 xterm上で gcc ファイル名.c と入力 その後xterm上で後一つコマンドを入力すればいいのですが、そのコマンドを忘れてしまいました。教えていただければ、ありがたいです。

  • C言語でホスト(Unix)にプログラム/プロセスを送信して実行する方法

    C言語でホスト(Unix)にプログラム/プロセスを送信して実行する方法を探しています。 用途はまだ具体的に決まってませんが 例えば、ある与えられたコマンドを各ホストに一斉送信して その結果をまとめて取得する、ようなことがしたいです。 どんなに難しくなってもいいので、いい方法や関数があったら教えて下さい。

  • C#の実行関数トレース

    C#プログラムのプロジェクトに途中から参画しています。 まだプログラムの全容を理解していないため、どのメニューを実行したときにどの関数が呼ばれるのか、を追うだけでいちいち時間がかかってしまい、困っています。 あるメニューを実行したときにコールされる関数名をすべて出力できるような方法やツールはありますか?

  • C言語からC++の関数をコールする方法について

    初めて質問させて頂きます。 質問は2つあります。 ●1つ目の質問です。 この度、C言語ベースのプログラムに、C++で作成した関数を使用することになりました。 方法としてextern等を駆使しつつ、ラッパー関数を使って対応しております。 そこで質問なのですが、この場合、ラッパー関数に使用するファイル形式はcppまたはcのどちらが正しいのでしょうか?(どちらでも動きました) ●2つ目の質問です。 Windows環境(vs2005)では無事、CからC++の関数を呼ぶことに成功はしました。 しかし、本当に動かしたいのはLinuxでの環境になります。 先程作成したラッパー関数のファイルとC++で作成した関数のファイルをライブラリ(soファイル)化したものを使用し、コンパイルとリンクは問題なく通すことに成功したのですが、 実行させてみると、Cの関数からラッパー関数をコールしているのは確実なのですが、ラッパー関数の処理を通らず、プログラムが止まってしまいます。 試しにラッパー関数の処理を「return 0;」だけにして実行させてみましたが現象は変わらずでした。 そのため、ラッパー関数を呼ぶための何かに問題があると思っています。 ここで質問なのですが、ビルドのときにライブラリをリンクさせるだけでは駄目なのでしょうか。また、他に思い当たることがありましたらご教示頂きたいです。 Windows環境(vs2005)では期待する動作をしているためプログラムは問題ないと思っています。