0

サーバー上のクライアントからデータを読み取るときに問題が発生しました。read()関数は、すべてのデータが読み取られ、私にとって望ましくないデータが増えるのを待った後、常にフリーズ(ブロック)します。

サーバープログラム:

   soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
   struct sockaddr_in sin;  
   sin.sin_family = AF_INET;  
   sin.sin_port = htons(port);   
   sin.sin_addr.s_addr = INADDR_ANY; 
   bind(soc, (struct sockaddr*) &sin, sizeof(sin));

   if (listen(soc, MAX))
      return;

   int socc;               // socket for clinet     
   while (1) {
      if ((socc = accept(soc, (struct sockaddr *) &sin, sinlen)) < 0)
         break;
      while ((result = read(socc, pointer, SIZE)) > 0) {
         // after the data are readed, read function will block
      }
      // do some stuff and write reply to client => will never done
   }

クライアントプログラム:

   ...
   soc = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)  
   struct sockaddr_in socketAddr;
   socketAddr.sin_family = AF_INET;
   socketAddr.sin_port = htons(port);
   memcpy(&(socketAddr.sin_addr), host->h_addr, host->h_length);
   if (connect(soc, (sockaddr *)&socketAddr, sizeof(socketAddr)) == -1)  
      return;
   if (write(soc, req.c_str(), strlen(req.c_str())) < 0)
      return;

主な問題は、クライアントがサーバーに送信するデータの量がわからないことです。そのため、サーバーはソケットからすべてのデータを読み取る必要があり、何も表示されなくなったら、読み取りサイクルを終了します。しかし、サーバーはたとえばメッセージ全体(30バイト)を読み取り、さらに待機します(ただし、これ以上は送信されません)。クライアントがサーバーからの応答を待っているため、ソケットはまだ開いています。

4

2 に答える 2

2

ソケットを非ブロッキングにする必要があります。その場合、特定のエラーで読み取るものがない場合、読み取りはすぐに終了します。

C-Unixソケットを見てください-ノンブロッキング読み取り

于 2013-03-10T05:40:31.317 に答える
2

前に述べたように、ノンブロッキングを使用するか、RCV_TIMEOUTをソケットに追加します。

struct timeval tv;

tv.tv_sec = 30;  /* 30 Secs Timeout */

setsockopt(sockid, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval));
于 2013-03-10T05:47:55.227 に答える