4

外部コントローラーは、TCP/IP ソケットを介して 30ms ごとに 120 バイトのメッセージを送信します。アプリケーションは、標準の tcp/ip ソケット recv 関数を介してこのメ​​ッセージを受信します。Linux および OSX で完全に動作します (recv は 30 ミリ秒ごとに 120 バイトのメッセージを返します)。Windows では、recv は約 1 秒ごとに ~3500 バイトのバッファを返します。それ以外の時間は 0 を返します。

Windows tcp ソケットを適切に (遅滞なく) 動作させる方法は?

PS: 私は既に TCP_NODELAY と TcpAckFrequency で遊んだことがあります。Wireshark は、すべてが正常であることを示しています。だから、それはWindowsの最適化だと思うので、オフにする必要があります。

読む -

int WMaster::DataRead(void)
{
if (!open_ok)  return 0;
if (!CheckSocket())
{
    PrintErrNo();
    return 0;
}
iResult = recv(ConnectSocket, (char *)input_buff,sizeof(input_buff),0);

nError=WSAGetLastError();
if(nError==0) return iResult;
if(nError==WSAEWOULDBLOCK) return iResult;

PrintErrNo();
return 0;
}

初期化-

ConnectSocket = INVALID_SOCKET;

iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&clientService, sizeof(clientService));
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr( deviceName.toLatin1().constData() );
clientService.sin_port = htons( port);

iResult = setsockopt(ConnectSocket, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, 
sizeof (int));

u_long iMode=1;
iResult=ioctlsocket(ConnectSocket,FIONBIO,&iMode);

iResult = ::connect( ConnectSocket, (SOCKADDR*) &clientService, 
sizeof(clientService) );

チェックソケット -

bool WMaster::CheckSocket(void)
{
socklen_t len = sizeof (int);
int retval = getsockopt (ConnectSocket, SOL_SOCKET, SO_ERROR, (char*)(&valopt), &len );
if (retval!=0)
{
   open_ok=false;
   return false;
};
return true;
}
4

2 に答える 2

1

Nagle アルゴリズムを無効にすることを検討してください。120 バイトは非常に小さいため、データが送信される前にバッファリングされる可能性があります。Nagle アルゴリズムであると私が考えるもう 1 つの理由は、1 秒間に約 33 回の送信が発生する必要があることです。これ33*120 = 3960 bytes / secは、ご覧の 3500 と非常によく似ています。

于 2013-03-23T16:12:02.130 に答える
0

エラーが発生した場合にのみ WSAGetLastError が呼び出されるように、dataread 関数を次のように変更します。

int WMaster::DataRead(void)
{
  if (!open_ok)  return 0;
  if (!CheckSocket())
  {
      PrintErrNo();
      return 0;
  }
  iResult = recv(ConnectSocket, (char *)input_buff,sizeof(input_buff),0);
  if(iResult >= 0)
  {
      return iResult;
  }

  nError=WSAGetLastError();
  if(nError==WSAEWOULDBLOCK) return iResult;

   PrintErrNo();
   return 0;
}

ミリ秒ごとにソケットをポーリングしているという事実は、パフォーマンスの問題に関係している可能性があります。しかし、それを問題と結論付ける前に、CheckSocket のソースを確認したいと思います。

于 2013-03-25T17:09:44.700 に答える