2012-02-12 8 views
0

Cでサーバークライアントモデルを構築しています。クライアントはサーバーに接続し、データの交換を開始します。ただし、ユーザーはプログラムの任意の時点でクライアントを終了できますが、サーバーには通知されません。サーバーは、クライアントが閉じられた後でもそのデータを送信し続けます。私は機能を送る印象にあった は-1を返しますサーバーは、データを送信することができませんが、私のサーバプログラムは、単にプログラムがちょうど上記の行で停止し、送信サーバープログラムが送信時にスタックされました

if((byteSent = send(new_fd, fileContents, strlen(fileContents), 0)) == -1){ // 

で立ち往生している場合。

どのようにこの問題を解決できますか?

//コード

exitT = 0; 
    //execution_count = 1; 
    for(i=0;i<execution_count;i++) 
    { 
     sleep(time_delay); 

     //getting the current time on the server machine 
     time_t t; 
     time(&t); 

     char *time=ctime(&t); 
     printf("The Execution time at server = %s\n",time); 

     system(exec_command); 

     /*Open the file, get file size, read the contents and close the file*/ 

     // Open the file 
     fp = fopen(fileName,"r"); 

     // Get File Size 
     fseek(fp,0,SEEK_END); 
     dataLength = ftell(fp); 
     rewind(fp);     

     fileContents = (char*)malloc(dataLength+1); 
     // Read File 
     fread(fileContents,1,dataLength,fp); 
     fileContents[dataLength] = '\0'; 

     // Close file 
     fclose(fp);  

     printf("sockfd = %d \n",new_fd); 
     // send file length to client 
     rc=send(new_fd, &dataLength, sizeof(dataLength), 0) ; 

     printf("length of client data = %d \n",rc); 

     printf("sockfd = %d \n",new_fd); 
     // send time to client 
     rc=send(new_fd, time, strlen(time), 0) ; 

     printf("length of client time = %d \n",rc); 

     usleep(20000); 

     // Send file contents to Client 
     while(dataLength>0){ 
      printf("sockfd = %d \n",new_fd); 
      if((byteSent = send(new_fd, fileContents, strlen(fileContents), 0)) == -1){ 
       printf("bytes sent = %d \n",byteSent); 
       exitT = 1; 
       break; 
      } 
      dataLength-=byteSent; 
     } 

     //Delete the log file 
     sprintf(deleteCommand,"rm %s",fileName); 
     system(deleteCommand); 
     if(exitT == 1) 
      break; 
    } 

     bzero(fileName,sizeof(fileName)); 
     bzero(exec_command,sizeof(exec_command)); 
     bzero(deleteCommand,sizeof(deleteCommand)); 

     //decClientNum(); 
     kill(parent_id,SIGALRM); 
     close(new_fd); // parent doesn't need this 
     printf("STATUS = CLOSED\n"); 

     exit(0); 
    } 

おかげ

+0

さらにコードを表示してください。 – ThiefMaster

答えて

1

あなたはLinuxまたはPosixシステムをコーディングしていると仮定します。

sendなどのシステムコールが失敗した場合は-1を返し、errnoを設定します。なぜ失敗したのかを知るには、おそらくerrnoを使うべきです。

straceを使用して、サーバーによって実行されたsyscallやその他のものを確認できます。もちろん、gdbデバッガも使用してください。

おそらく入力または出力を多重化する必要があります。システムコールは、poll,select(およびそれに関連するppollおよびpselect)です。例: select_tut(2)のマニュアルページを参照してください。

あなたも、GUIの外で使用されるかもしれない、両方のGtkとQtフレームワークは、独自に提供(..使用する(または少なくとものソースコードを勉強する)libeventlibevなどのような既存のイベント指向のライブラリとよいでしょうアプリケーション)。

advanced unix programmingunix network programing(とおそらく約advanced linux programming)について読むことを強くお勧めします。

+0

通常、宿題ではそのようなライブラリを使用できません。これは、低レベルのソケット関数を扱い、それらを使用する方法を学ぶという目的をかなり破ります。 – ThiefMaster

+0

しかし、彼らは少なくともソースコードを勉強して多くのことを学ぶことができます。 –

+0

確かに - 単純な割り当てのために、それは通常、あまりにも複雑すぎます。 – ThiefMaster

0

多分あなたは、TCPプロトコルを使用していると、サーバはACKを待っています。接続を非同期にする場合は、udpを使用してみてください。

+0

これは私のネットワーク割り当ての一部であり、TCPを使用する必要があります –

0

マニュアルページから:配信に失敗したことの兆候はsend()に暗黙的に示されていません。局所的に検出されたエラーは、戻り値-1で示されます。

Proablyこのようなものが役立つかもしれない:http://stefan.buettcher.org/cs/conn_closed.html

+0

この例は、サーバーがクライアントから何かを受信して​​いることを示しています。パイプに何もない場合、クライアントはクローズされているとみなします。しかし私のプログラムでは、サーバーがクライアントにデータを送信しているときにクライアントが閉じられます。私のサーバープログラムはsend()関数で停止します。受信フラグはsend()関数では機能しません。 –

0

を私はかなり遅くパーティーでだと思うが、私はこの答えは、誰かを助けるかもしれないと思います。

メッセージを送信するために送信ソケットに空き領域がなく、ソケットファイル記述子にO_NONBLOCKが設定されていない場合、send()は空きができるまでブロックします。

send()関数がスタックすると、TCPウィンドウサイズが0になったような状況が発生する可能性があります。接続のもう一方の端が受信データを消費していない場合に発生します。

このようなシナリオがある可能性があります。受信側プロセスはGDBによって実行されており、segfaultが発生しました。

  1. TCP接続が確立されたままです。
  2. データが継続的に送信されています。
  3. 受信側はそれを消費していません。

したがって、受信者のTCPウィンドウサイズは減少し続け、ゼロより大きくなるまでデータを送信できます。一度0になると、send()関数は永遠に止まってしまいます。

質問に記載されている状況は閉じた接続のシナリオではありません。プロセスが閉じたTCP接続に何かを書き込むと、シグナルSIGPIPEを受信します。 SIGPIPEのデフォルトハンドラはプロセスを終了します。したがって、クローズされた接続シナリオでは、独自のSIGPIPEハンドラを使用していない場合は、何かがソケットに書き込まれるたびにプロセスがデフォルトのハンドラで終了する必要があります。

関連する問題