web-dev-qa-db-ja.com

TCPソケットを非ブロッキングに変更するにはどうすればよいですか?

ソケットを非ブロッキングにする方法は?

fcntl()関数は知っていますが、必ずしも信頼できるとは限りません。

34

「常に信頼できるとは限らない」とはどういう意味ですか?システムがソケットの非ノンブロッキング設定に成功すると、非ブロッキングになります。ソケット操作は、ブロックする必要がある場合にEWOULDBLOCKを返します(たとえば、出力バッファーがいっぱいで、send/writeを頻繁に呼び出している場合)。

このフォーラムスレッド ノンブロッキングコールで作業する場合、いくつかの良い点があります。

21
unwind

fcntl() は私にとって常に確実に機能しました。いずれにせよ、ソケットのブロックを有効/無効にするために使用する関数は次のとおりです。

#include <fcntl.h>

/** Returns true on success, or false if there was an error */
bool SetSocketBlockingEnabled(int fd, bool blocking)
{
   if (fd < 0) return false;

#ifdef _WIN32
   unsigned long mode = blocking ? 0 : 1;
   return (ioctlsocket(fd, FIONBIO, &mode) == 0) ? true : false;
#else
   int flags = fcntl(fd, F_GETFL, 0);
   if (flags == -1) return false;
   flags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK);
   return (fcntl(fd, F_SETFL, flags) == 0) ? true : false;
#endif
}
82
Jeremy Friesner

fcntl()が常に信頼できるとは限らないという誤った情報があります。それは真実ではありません。

ソケットを非ブロックとしてマークするには、コードは次のように簡単です。

_// where socketfd is the socket you want to make non-blocking
int status = fcntl(socketfd, F_SETFL, fcntl(socketfd, F_GETFL, 0) | O_NONBLOCK);

if (status == -1){
  perror("calling fcntl");
  // handle the error.  By the way, I've never seen fcntl fail in this way
}
_

Linuxでは、2.6.27を超えるカーネルでは、 socket() および accept4() を使用して、最初からノンブロッキングのソケットを作成することもできます。 。

例えば.

_   // client side
   int socketfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);

   // server side - see man page for accept4 under linux 
   int socketfd = accept4( ... , SOCK_NONBLOCK);
_

少しの作業は節約できますが、移植性が低いため、fcntl()で設定する傾向があります。

46
Matt

fcntl()またはioctl()は、ファイルストリームのプロパティを設定するために使用されます。この関数を使用してソケットを非ブロッキングにすると、accept()recv()などのような、本来ブロッキングしている関数はエラーを返し、errnoEWOULDBLOCKに設定します。ファイル記述子セットをポーリングして、ソケットでポーリングできます。

16
Siva

通常、通常のブロッキングIOmultiplexingを使用して同じ効果を達成できます。いくつかのIO select(2)poll(2)、またはシステムで使用可能な他のシステムコールを使用した操作。

スケーラブルIO多重化へのアプローチの比較については C10K問題 を参照してください。

2

私はそれが古い質問であることを知っていますが、ここでブロックおよび非ブロッキングソケットを処理する方法に関する情報を探しているGoogleのすべての人にとって、ソケットのI/Oモードを処理するさまざまな方法の詳細な説明です- http://dwise1.net/pgm/sockets/blocking.html

簡単な要約:

  • では、なぜソケットがブロックするのですか?

  • ブロッキングソケットを処理するための基本的なプログラミング手法は何ですか?

    • ブロックを気にしないデザインを持っている
    • selectの使用
    • 非ブロッキングソケットの使用
    • マルチスレッドまたはマルチタスクの使用

Cでソケットを非ブロッキングとして設定する最良の方法は、ioctlを使用することです。受け入れられたソケットが非ブロックに設定されている例は次のとおりです。

long on = 1L;
unsigned int len;
struct sockaddr_storage remoteAddress;
len = sizeof(remoteAddress);
int socket = accept(listenSocket, (struct sockaddr *)&remoteAddress, &len)
if (ioctl(socket, (int)FIONBIO, (char *)&on))
{
    printf("ioctl FIONBIO call failed\n");
}
1
Steve Wranovsky