2009-07-02 4 views
0

작성한 UDPSocket 래퍼에 문제가 있습니다. 나는 UDP 패킷을 앞뒤로 보내고있는 높은 대역폭의 낮은 대기 시간의 로컬 네트워크를 가지고있다. 나는 패킷 도착의 신뢰성에 대해 너무 많은 걱정을하지 않지만, 도착한 패킷이 그렇게 빨리 이루어 지도록하는 것은 매우 중요합니다. 여기에 소켓을 설정하기위한 관련 코드입니다 :UDP 지연을 통한 WinXP 리눅스

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(). 한편으로 리눅스 측은 실제적으로 즉시 수신되는 것으로 보이지만 윈도우 측은 데이터를 수신하기까지 최대 1 초의 지연이 있습니다. 그러나 :: recv()는이 시간에 0을 반환하지 않습니다. 나는 명백한 것을 놓치고 있는가?

+0

아직 의견을 게시 할 수없는 Mike Simpson의 신사가 같은 문제를 겪고 있습니다. 이 항목을 알아내는 데 여전히 관심이 있다면 [email protected]으로 전화를 끊을 수 있습니까? 제발 고마워. 그렇지 않으면 해를 입지 않습니다. –

답변

1

네 가지 조합을 모두 시도해 보셨습니까 (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 선택 구현을 신뢰하지 않았습니다.