2009-07-02 12 views
0

私が書いたUDPSocketラッパーに問題があります。私は、UDPパケットを前後に送信する高帯域幅の低遅延ローカルネットワークを持っています。私はパケットの到着の信頼性についてあまり心配する必要はありませんが、到着するパケットが非常に速くなることは非常に重要です。ここではソケットを設定するための関連するコードは次のとおりです。LinuxからWinXPへのUDP遅れ

bool UDPSocket::create() { 
    int on = 1; 
#ifdef WIN32 
    if(WSAStartup(MAKEWORD(1,1), &SocketInfo) != 0) { 
     MessageBox(NULL, "Cannot initialize WinSock", "WSAStartup", MB_OK); 
    } 
#endif 
    m_sock = socket(PF_INET, SOCK_DGRAM, 0); 
#ifdef WIN32 
    if(setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == SOCKET_ERROR) 
     return false; 
#else 
    if(setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on)) == -1) 
     return false; 
#endif 
    addrLen = sizeof(struct sockaddr); 
    return true; 
} 

bool UDPSocket::bind(const int port) { 
    if(!is_valid()) 
     return false; 
    m_addr.sin_family = AF_INET; 
    m_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
    m_addr.sin_port = htons(port); 

    if(::bind(m_sock, (struct sockaddr*)&m_addr, sizeof(m_addr))<0) { 
     std::cout << "UDPSocket: error on bind" << std::endl; 
     return false; 
    } 
    return true; 
} 
bool UDPSocket::send(const std::string s) const { 
    const char* buf = s.c_str(); 

    ::sendto(m_sock, buf, strlen(buf), 0, (const sockaddr*)&clientAddr, addrLen); 
    return true; 
} 

bool UDPSocket::setDestination(const std::string ip, const int port) { 
    memset(&clientAddr, 0, sizeof(clientAddr)); 

    clientAddr.sin_family = AF_INET; 
    clientAddr.sin_addr.s_addr = inet_addr(ip.c_str()); 
    clientAddr.sin_port = htons(port); 

    return true; 
} 

int UDPSocket::recv(std::string& s) const { 
    char buffer[MAXRECV + 1]; 
    struct timeval tv; 
    fd_set fdset; 
    int rc, nread; 

    memset(&buffer, 0, sizeof(buffer)); 

    FD_ZERO(&fdset); 
    FD_SET(m_sock, &fdset); 

    tv.tv_sec = 0; 
    tv.tv_usec = m_timeout; 

    rc = select(m_sock + 1, &fdset, (fd_set *) 0, (fd_set *) 0, &tv); 

    if(FD_ISSET(m_sock, &fdset)) { 
#ifdef WIN32 
     nread = ::recvfrom(m_sock, buffer, MAXRECV, 0, (sockaddr*)&clientAddr, const_cast< int * __w64 >(&addrLen)); 
#else 
     nread = ::recvfrom(m_sock, buffer, MAXRECV, 0, (sockaddr*)&clientAddr, (socklen_t*)&addrLen); 
#endif 
     if(nread < 0) { 
      return -1; 
     } else if(nread == 0) { 
      return 0; 
     } 
     s = std::string(buffer); 
     return nread; 
    } else { 
     return 0; 
    } 
} 
void UDPSocket::set_non_blocking(const bool b) { 
    mNonBlocking = b; 
#ifdef WIN32 
    u_long argp = b ? 1 : 0; 
    ioctlsocket(m_sock, FIONBIO, &argp); 
#else 
    int opts = fcntl(m_sock, F_GETFL); 
    if(opts < 0) return; 
    if(b) 
     opts |= O_NONBLOCK; 
    else 
     opts &= ~O_NONBLOCK; 

    fcntl(m_sock, F_SETFL, opts); 
#endif 
} 

両端に私のユーザーコードは、「送信」とUDPSocket「を受信」とそれぞれのポートにバインドを作成し、送信する()送信を使用します受信するデータとrecv()。一方で、Linux側は実質的にすぐに受信されるようですが、Windows側ではデータを受信するまでに最大1秒の遅延があります。ただし、:: recv()はこの時点では0を返しません。私は明白な何かを欠いていますか

+0

まだコメントしていないMike Simpson氏の紳士が同じ問題にぶつかっています。あなたはまだこの1つを考え出すことに興味があるなら、あなたは[email protected]で彼にラインを落とすことができますか?どうかありがとうございます。そうでない場合、害はありません。 –

答えて

1

あなたは4つの組み合わせ(linux-> linux、win-> linux、linux-> win、win-> win)を試しましたか?遅延があり、それはありませんか?

また、パケットスニファ(tcpdumpまたはwiresharkなど)を使用して、遅延がワイヤに当たる前か後であるかどうかを確認します。

0

これは直接的な回答ではありません。あなたはttcp (http://www.pcausa.com/Utilities/pcattcp.htm)のようなツールを試すことができます。これは、tcpとudpの両方の性能をテストすることができます。また、パブリックドメインにあるソースコードを確認することもできます。

0

実験の時間がある場合は、IOCP版のコードを試してみてください。

64ソケットの制限を持つwin selectの実装は信頼できませんでした。

関連する問題