select関数による切断の通知について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
shiro4ao
記事: 224
登録日時: 14年前
住所: 広島

select関数による切断の通知について

#1

投稿記事 by shiro4ao » 14年前

select()を(ラップした関数)つかって非同期通信を
つくろうとしているのですが
相手が切断してきたときの処理ができません。
select()に切断を通知する機能はありますか?
それとも根本的におかしいでしょうか?


コード:

#include    <stdio.h>
#include    <conio.h>
#include    <winsock2.h>

//読み込めるソケットを返してくれる
int GetReadableSock( unsigned int s[] ,int N)
{
  int i;
  fd_set fdset;

  // fd_set変数を0に初期化する
  FD_ZERO( &fdset );
  // 各ソケットの番号を登録する
  for( i=0; i<N; i++ ){
    FD_SET( s[i], &fdset );
  }

  // ソケット番号の最大値を探す
  int max_s=0;
  for( i=0; i<N; i++ ){
    if( max_s < s[i] ) max_s = s[i];
  }

  // タイムアウトを10秒に設定
  struct timeval tv;
  tv.tv_sec  = 100000;
  tv.tv_usec =  0;

  // ソケットにデータが届くまで待つ
  int n = select( max_s+1, &fdset, NULL, NULL, &tv );

  if( n == -1 ){ // 何らかのエラー
    perror("select");
    return 0;
  }else if( n == 0 ){ // タイムアウト
    fprintf( stderr, "select timeout\n" );
    return 0;
  }else if( n>0 ){ // どれかにデータが届いた
    // どれが読み込み可能か検査
    for( i=0; i<N; i++ ){
      if( FD_ISSET( s[i], &fdset ) ){
	return s[i]; // 読み込めるソケットを返す
      }
    }
    return 0;
  }
  return 0;
}

int main(void)
{ 
    WSADATA wsaData;
    SOCKET  ServSock,readable;
    SOCKET  ClientSock[2];
    struct  sockaddr_in addr;
    struct  sockaddr_in client;
    struct  sockaddr_in client2;
    int     len,i=0,ret;
   unsigned  char *buf,tmp[5024];



    if (WSAStartup(MAKEWORD(2,0), &wsaData))
    ServSock= socket(AF_INET,SOCK_STREAM,0);


    addr.sin_family = AF_INET;
    addr.sin_port = htons(5900);
    addr.sin_addr.S_un.S_addr = INADDR_ANY;
    bind(ServSock, (struct sockaddr *)&addr, sizeof(addr));
    printf("接続待ちです\n");

    listen(ServSock, 5);

    // TCPクライアントからの接続要求を受け付ける
    len = sizeof(client);
    ClientSock[0] = accept(ServSock, (struct sockaddr *)&client, &len);
    ClientSock[1] = accept(ServSock, (struct sockaddr *)&client2, &len);




     buf=(char *)malloc(sizeof(char)*500000);


     while(1){

	readable=GetReadableSock(ClientSock,2);

	memset(buf,'\0',sizeof(buf));

	if(ClientSock[1]==readable){
		ret=recv(ClientSock[1],buf,500000,0);
		ret=send(ClientSock[0],buf,ret,0);
	}

	if(ClientSock[0]==readable){
		ret=recv(ClientSock[0],buf,500000,0);
		send(ClientSock[1],buf,ret,0);
	}

   }

    closesocket(ServSock);
    closesocket(ClientSock[0]);
    closesocket(ClientSock[1]);

    WSACleanup();
    return 0;
}
 

たろ

Re: select関数による切断の通知について

#2

投稿記事 by たろ » 14年前

あまり詳しくないですが・・
とりあえず私の環境ではプログラムはWSAStartup()のif判定を修正しないと動きませんでした。
接続してきたクライアント2つの間で、チャットみたいな?やりとりをするサーバプログラムなんですね。

コネクションの切断は、「recv()の戻り値がゼロ」ということらしいです。

2.12 - TCPコネクションが close されたことをどうやって検出できますか?
http://www.kt.rim.or.jp/~ksk/wskfaq-ja/ ... ormalclose
・・。通信相手がコネクションを閉じると recv() は 0 を返却します。・・
例えば切断を検出してwhileループを抜ける場合の処理は、こんな感じでしょうか。
ret = recv(..);
if( ret==0 ) break;

このままだと、切断検出と共にサーバプログラムも終了しますが・・。

アバター
shiro4ao
記事: 224
登録日時: 14年前
住所: 広島

Re: select関数による切断の通知について

#3

投稿記事 by shiro4ao » 14年前

recv()の戻り値を判定させたら上手く終了してくれました!
ありがとうございました。。

閉鎖

“C言語何でも質問掲示板” へ戻る