2011-11-12 13 views
4

私は簡単なクライアント - サーバーチャットプログラムを作ろうとしています。クライアント側では、別のスレッドをスピンオフして、サーバからのデータを読み込みます。問題は、人がメインスレッドからログアウトしたときに、その2番目のスレッドを正常に終了させたいということです。私は共有変数 'を使用して終了しようとしていた問題は、ソケットの読み取り()コマンドはブロックコマンドですので、(実行== 1)、サーバーは何かを返す前に送信する必要がありますwhile条件を再度確認することができます。私はノンブロッキングの読み込みを行うためのメソッド(一般的なunixソケットのみ)を探しています。基本的にはpeek()のいくつかの形式が動作します。C - Unixソケット - 非ブロック読み取り

読み込みスレッドのループは以下の通りですが、今は共有変数にはミューテックスがありませんが、後で追加する予定です。 ;)

void *serverlisten(void *vargp) 
{ 
    while(running == 1) 
    { 
     read(socket, readbuffer, sizeof(readbuffer)); 
     printf("CLIENT RECIEVED: %s\n", readbuffer); 
    } 
    pthread_exit(NULL); 
} 

答えて

8

あなたは別のポストで提案されているように、ソケットがブロック可能ではない作るプラスのように、タイムアウトで入力を待つことを選択し使用することができます:オプションSO_RCVTIMEOと機能setsockoptため

fd_set   input; 
FD_ZERO(&input); 
FD_SET(sd, &input); 
struct timeval timeout; 
timeout.tv_sec = sec; 
timeout.tv_usec = msec * 1000; 
int n = select(sd + 1, &input, NULL, NULL, &timeout); 
if (n == -1) { 
    //something wrong 
} else if (n == 0) 
    continue;//timeout 
if (!FD_ISSET(sd, &input)) 
    ;//again something wrong 
//here we can call not blockable read 
+0

このコンテキストでは、sd + 1の意味は何ですか?私はこのように走ったが、それはうまくいったが、20时间のようにループをループし、新しい入力が作成されるまで停止したが、私が望むように優雅に終了した。タイムアウトなどの間に実行していたのとほとんど同じです – will

+0

端末に「man select」と入力すると、選択機能の詳細な説明が表示されます。最初の引数selctは値記述子に1を加えた値が最大になります。ここでは1つの記述子しかないので、私は(sd + 1)と書くだけです。 – fghj

+0

約20回のメモを理解できません。あなたの最初の質問のコンテキストで私のコードは、次のように動作する必要があります:1)チェックフラグ(終了する時間?)2)入力またはタイムアウトまでスリープ状態3)何かを読んで4)goto(1)。だから、少し遅れて出る。しかし、あなたは状況を処理する必要があります他の側の近くの接続、あなたに戻ってコントロールを選択するが、 "読み取り" 0バイトを読み取ると、ビジーループを取得します。ですから、 "read"の結果をチェックし、ゼロの場合はループを終了する必要があります。 – fghj

6
fcntl(socket, F_SETFL, O_NONBLOCK); 

か、あなたは他のフラグを持っている場合:

int x; 
x=fcntl(socket ,F_GETFL, 0); 
fcntl(socket, F_SETFL, x | O_NONBLOCK); 

は、利用可能なデータがあったかどうかを確認するために、読み取りの戻り値を確認してください。

注:グーグルでは、フルのの例がたくさんあります。

ブロッキングソケットを使用して、「peek」とselectをタイムアウトで使用することもできます。それはここでより適切に思われるので、あなたは忙しい待つことはありません。

2

最高のものは、余分なスレッドを取り除き、select()またはpoll()を使用してすべてを1つのスレッドで処理する可能性が高いです。

スレッドを維持したい場合は、ソケットのshutdown()を呼び出して接続をシャットダウンし、ブロックされているすべてのスレッドを起動しますが、ファイル記述子は有効にしてください。リーダースレッドに参加したら、ソケットを閉じることができます。これはソケット上でのみ機能し、他のタイプのファイル記述子では機能しないことに注意してください。

0

これは特定の回答ではない場合がありますが、それが見つかる場所である可能性があります。

Unix Network Programming, Volume 1: The Sockets Networking API, 3rd Edition

をマルチスレッド、ノンブロッキング・サーバーとクライアントの例がたくさんあります:私は現在読んでいます。また、さまざまな方法の間にある多くの推論とトレードオフについて説明します。

希望するもの...

+0

広告のリンク。素晴らしい動き! ;) –

+0

@ YagamyLight好きな広告以外のリンクを追加することは大歓迎です。私はAmazonやAddison-Wesleyと提携していません。しかし、Amazonにリンクすると、購買可能、プレビュー、レビューが可能になり、一般的には近い将来有効期限が切れる安定したURLになります。 – Homer6

+0

私はアマゾンを意味しませんでした、私は、リンク自体が謎めいた[rads.stackoverflow.com](http://rads.stackoverflow.com/amzn/click/0131411551)によって作られたことを意味しました。しかし、それは、私はすでにあなたの記事でこのリンクではないことがわかったので、これはStackOverflow自体のいたずらであるようです。 Btw、ちょっと好奇心 - あなたはポストの中でそのようなリンクを見ますか(私はリンクが作者から隠されていると思っただけです)? –

関連する問題