【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は謹んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.19676

listen関数後のfprintf出力で止まっているのは何故?
投稿者---chikato(2005/02/01 03:12:00)


Win2k+Cygwinの環境です。
Cプログラミングの学習を始めました。

以下の様なリストtest.cを試してみました。
処理状況を見るために途中、
printf("処理A地点");とprintf("処理A地点");を挿入しています。
ところが

$ gcc -o test test.c
$ ./test.exe
Input port number:50000
successfully bound, now waiting.

で止まってしまい、
「処理A地点」が表示されません。
どうして、表示されないのでしょうか?


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <curses.h>
#include <signal.h>
#include <unistd.h>
#define BUF_LEN 20
static int width;
static fd_set mask;
static char buf[BUF_LEN]; /* 送受信兼用バッファ */
static int session_soc; /* socket */

int setup_server(in_port_t port){
 struct sockaddr_in me; /* 自分のソケットのアドレス */
 int soc_waiting; /* 接続待ちのソケット */
 int soc; /* 通信に使うソケット */

 /* 自分のアドレスを sockaddr_in 構造体に設定 */
 memset((char *)&me, 0, sizeof(me));
 me.sin_family = AF_INET;
 me.sin_addr.s_addr = htonl(INADDR_ANY);
 me.sin_port = htons(port);

 /* IPv4 でストリーム型のソケットの作成 */
 if ((soc_waiting = socket(AF_INET,SOCK_STREAM,0)) < 0 ){
  perror("socket");
  return -1;
 }

 /* ソケットに自分のアドレスを設定 */
 if (bind(soc_waiting,(struct sockaddr *)&me,sizeof(me)) == -1){
  perror("bind");
 return -1;
 }

 /* ソケットで接続待ちの設定 */
 listen(soc_waiting,1);
 fprintf(stderr,"successfully bound, now waiting.\n");
 printf("処理A地点");
 /* 接続要求があるまでブロック */
 soc = accept(soc_waiting, NULL, NULL);
 
 printf("処理B地点");
 
 /* 接続待ちに使ったソケットを閉じる */
 close(soc_waiting);

 /* 通信に使うソケットのディスクリプタを返す */
 return soc;
}

int main(void){
 int soc; /* ソケットのディスクリプタ */
 char port0[12];
 in_port_t port;
 printf("Input port number:");
 fgets(port0,sizeof(port0),stdin);
 port=atoi(port0);
 printf("port=%u",port); // in_port_t型はunit16_t型

 /* 接続受付まで */
 if( (soc = setup_server(port) ) == -1)exit(1);
 return 0;
}




この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:listen関数後のfprintf出力で止まっているのは何故? 19677 NykR 2005/02/01 05:05:54


No.19677

Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---NykR(2005/02/01 05:05:54)


Win2k+Cygwinの環境です。
Cプログラミングの学習を始めました。

以下の様なリストtest.cを試してみました。
処理状況を見るために途中、
printf("処理A地点");とprintf("処理A地点");を挿入しています。
ところが

$ gcc -o test test.c
$ ./test.exe
Input port number:50000
successfully bound, now waiting.

で止まってしまい、
「処理A地点」が表示されません。
どうして、表示されないのでしょうか?


バッファリングしているからです。
標準エラー出力に出力するか、改行するか、フラッシュするか、標準出力をバッファリングなしに設定するかすれば表示されます。


この投稿にコメントする

削除パスワード

No.19678

Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---chikato(2005/02/01 11:49:38)


有難うございます。

> バッファリングしているからです。
「fprintf(stderr,…」はバッファリングするのですね。

実験的に
#include<stdio.h>
int main(void){
fprintf(stderr,"successfully bound, now waiting.\n");
return 0;
}
を試してみて、途中で止まるか見ましたが止まりませんでした。
これとどう違うのでしょうか?


この投稿にコメントする

削除パスワード

No.19680

Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---YuO(2005/02/01 14:03:28)


>> バッファリングしているからです。
>「fprintf(stderr,…」はバッファリングするのですね。

stdoutは完全バッファリングしますから,バッファが満杯にならないと出力されません。
stderrは完全バッファリングされませんから,最低でも改行文字を書き出せば出力されます。
#stdoutは対話型装置に接続されていると仮定。まぁ,普通なら問題ないですが。


さらに,直後のacceptによってプロセスが停止しますから,
stdoutへの出力は最低でもacceptするまで遅延します。


この投稿にコメントする

削除パスワード

No.19681

Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---chikato(2005/02/01 14:33:11)


ご回答有難うございます。


> stdoutは完全バッファリングしますから,バッファが満杯にならないと出力されませ
> ん。
[Enter]キーが押される(改行文字が入力される)かバッファ最大許容量に達さないと処理は次に進まないですね。

> stderrは完全バッファリングされませんから,最低でも改行文字を書き出せば出力さ
> れます。
では、私が挙げたリストではどうしてあそこで止まるんですかね?
(stderrなのに)

> さらに,直後のacceptによってプロセスが停止しますから,
> stdoutへの出力は最低でもacceptするまで遅延します。
エーと、 イマイチ意味が分かりません。

fprintf(stderr,"successfully bound, now waiting.\n");
printf("処理A地点");
/* 接続要求があるまでブロック */
soc = accept(soc_waiting, NULL, NULL);

では
fprintf(stderr,"successfully bound, now waiting.\n");

soc = accept(soc_waiting, NULL, NULL);

printf("処理A地点");

と処理が進むという意味でしょうか?



この投稿にコメントする

削除パスワード

No.19692

Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---かずま(2005/02/01 15:31:05)


> では、私が挙げたリストではどうしてあそこで止まるんですかね?
> (stderrなのに)
printf("処理A地点"); は stdout です。

次のようにすれば、出力されます。

printf("successfully bound, now waiting.\n");
fprintf(stderr, "処理A地点");




この投稿にコメントする

削除パスワード

No.19691

Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---かずま(2005/02/01 15:26:42)


> stdoutは完全バッファリングしますから,バッファが満杯にならないと出力されません。
> stderrは完全バッファリングされませんから,最低でも改行文字を書き出せば出力されます。
> #stdoutは対話型装置に接続されていると仮定。まぁ,普通なら問題ないですが。

ちがいます。

stdout が対話型装置に接続されている場合、行バッファリングになりますから、
バッファリングされた文字が出力されるのは、次のいずれかの場合です。
(1)バッファが満杯になったとき、
(2) 改行文字 '\n' がバッファに入れられたとき、
(3) fflush(stdout) または fclose(stdout) が実行されたとき、
(4) stdin からの入力が行われるとき

stderr はバッファリングされないので、すべての文字が一字ずつ出力されます。
改行文字かどうかは無関係。


この投稿にコメントする

削除パスワード

No.19694

Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---YuO(2005/02/01 17:05:04)


>> stdoutは完全バッファリングしますから,バッファが満杯にならないと出力されません。
>> stderrは完全バッファリングされませんから,最低でも改行文字を書き出せば出力されます。
>> #stdoutは対話型装置に接続されていると仮定。まぁ,普通なら問題ないですが。
>ちがいます。

確認しました。
#notを見忘れていた……。


>stderr はバッファリングされないので、すべての文字が一字ずつ出力されます。
>改行文字かどうかは無関係。

ん?
>the standard error stream is not fully buffered
としか書いていないのでは?
#つまり,行バッファリングはしてもよい。



この投稿にコメントする

削除パスワード

No.19698

Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---かずま(2005/02/02 02:56:11)


>>stderr はバッファリングされないので、すべての文字が一字ずつ出力されます。
>>改行文字かどうかは無関係。

>ん?
>>the standard error stream is not fully buffered
>としか書いていないのでは?
>#つまり,行バッファリングはしてもよい。
最初の質問者は、

> Win2k+Cygwinの環境です。

と、きちんと自分の環境を述べています。、

この環境では、stderr はバッファリング無しです。次のプログラムを実行すると、
stderr がバッファリング無し、stdout が行バッファリグであることが分かります。

#include <stdio.h>
#include <windows.h>

int main(void)
{
    char *p = "abcd\nefg";
    while (*p) {
        putc(*p++, stderr);  /* or putc(*p++, stdout); */
        Sleep(1000);
    }
    return 0;
}

Windows で、VC++ や BC++ を使うと、stdout もバッファリング無しです。

これは、規格書に

: As initially opened, the standard error stream is not fully buffered;
: the standard input and standard output streams are fully buffered if
: and only if the stream can be determined not to refer to an
: interactive device.

と、書かれているように stdout も stderr も完全バッファリングではないから
バッファリング無しでも、行バッファリングでも構わないわけです。

Cygwin の gcc では、stdout は行バッファリング、stderr はバッファリング無し。
Windoes の VC++ や BC++ では、stdout も stderr もバッファリング無し。

これらは、バッファリングについての

: Support for these characteristics is implementation-defined, and may be
: affected via the setbuf and setvbuf functions.

という記述からも問題ないわけですが、質問者が Cygwin といっている以上
それについての適切な説明(stderr はバッファリング無し)を無視して、一般的
な説明を行うことは質問者にかえって混乱を与えかねません。

しかも、stderr が行バッファリングをしている環境を私は見たことがありません。
ご存知でしたら、ご教示ください。



この投稿にコメントする

削除パスワード

No.19686

Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---かずま(2005/02/01 15:13:30)


>> バッファリングしているからです。
>「fprintf(stderr,…」はバッファリングするのですね。
ちがいます。

printf("xxx");          -- fprintf(stdout, "xxx"); と同じ。
fprintf(stdout, "xxx"); -- バッファリングされて出力は後。
fprintf(stderr, "xxx"); -- バッファリングされずに出力される。
printf("xxx\n");        -- バッファリングされるが、'\n' により出力される。
printf("xxx"); fflush(stdout); -- バッファリングされるが、fflush により
出力される。
setbuf(stdout, NULL); printf("xxx"); -- バッファリングされずに出力される。



この投稿にコメントする

削除パスワード

No.19711

(解決)Re:listen関数後のfprintf出力で止まっているのは何故?
投稿者---chikato(2005/02/03 13:57:25)


皆様、ご回答大変有難うございます。

> 次のようにすれば、出力されます。
> printf("successfully bound, now waiting.\n");
> fprintf(stderr, "処理A地点");
これで出力されました。

> printf("xxx"); -- fprintf(stdout, "xxx"); と同じ。
> fprintf(stdout, "xxx"); -- バッファリングされて出力は後。
> fprintf(stderr, "xxx"); -- バッファリングされずに出力される。
> printf("xxx\n"); -- バッファリングされるが、'\n' により出力される。
意味が理解できました。「\n」が必要だったのですね。

fprintf(stderr,"successfully bound, now waiting.\n");
printf("処理A地点\n");

として「処理A地点」も出力されました。


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧