我在client程序中同时使用TCP和UDP协议,首先是建立一个TCP的连接,然后用同样的端口打开一个UDP的端口,等待接收数据,我用的 select,可是接受不到数据,有时候能够接受,请问是什么原因,谁能帮忙高分相送HRESULT tcp_client::connect(const char *host_name, unsigned short port)
{
WORD wVersionRequested = MAKEWORD(2,2);

WSADATA wsaData; HRESULT nRet = WSAStartup(wVersionRequested, &wsaData); if (wsaData.wVersion != wVersionRequested)
{
netmsg("Wrong version of Winsock");
return EXIT_FAILURE;
}

LPHOSTENT he = gethostbyname(host_name); if (he == NULL)
{
netmsg("Error in gethostbyname()");
return EXIT_FAILURE;
} m_sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_sockfd == INVALID_SOCKET)
{
netmsg("Error on call to socket()");
return EXIT_FAILURE;
} SOCKADDR_IN their_addr; their_addr.sin_family = AF_INET;
their_addr.sin_addr = *((LPIN_ADDR)*he->h_addr_list); their_addr.sin_port = htons(port); nRet = ::connect(m_sockfd, (LPSOCKADDR)&their_addr, sizeof(struct sockaddr)); if (nRet == SOCKET_ERROR)
{
netmsg("Error on connect");
return EXIT_FAILURE;
}
#ifdef USE_UDP
if(FAILED(connectUDP(host_name,port) ))
{
netmsg("Error on connect()");
return EXIT_FAILURE;
}
#endif 
return nRet;
}HRESULT tcp_client::connectUDP(const char *host_name, unsigned short port)
{
int ret ;
SOCKADDR_IN local ;// myselfhost;
int namelen = sizeof(local);
//struct sockaddr_in 

ret = getsockname(m_sockfd, (struct sockaddr*)&local, &namelen) ;
if(SOCKET_ERROR == ret)
{
netmsg("error in getsockname") ; return EXIT_FAILURE ;
}
/*
myselfhost.sin_family = AF_INET ;
myselfhost.sin_addr.s_addr = htonl(INADDR_ANY) ;
myselfhost.sin_port = local.sin_port ;// htons(port);
*/ m_udpfd =  socket(AF_INET, SOCK_DGRAM, 0);

if (m_udpfd == INVALID_SOCKET)
{
netmsg("udp Error on call to socket");
return EXIT_FAILURE;
}

if((ret = bind(m_udpfd, (SOCKADDR*)&local,sizeof(local)))==SOCKET_ERROR)
{
netmsg("Error on UDP bind");
return EXIT_FAILURE;
}
return ret ;
}
HRESULT tcp_client::recv(char *data, int len)
{

if (!data)
{
return EXIT_FAILURE;
}
#ifdef USE_UDP
int max_fd ;
int hr = 0;
fd_set r_fdset ;
struct timeval timeval = {1,0};
RE_READ:
FD_ZERO(&r_fdset) ;
FD_SET(m_sockfd, &r_fdset) ;
FD_SET(m_udpfd, &r_fdset) ; max_fd = max(m_sockfd, m_udpfd)  ; int ret = select (max_fd+1, &r_fdset, NULL,NULL, &timeval) ;
switch(ret)
{
case 0 :
goto RE_READ ;
case -1:
break ;
default:
if(FD_ISSET(m_sockfd,&r_fdset))
{
hr = ::recv(m_sockfd, data, len, 0); 
}
else if(FD_ISSET(m_udpfd, &r_fdset) )
{
/*检查数据是否是来自我们的gameserver*/
hr = ::recv(m_udpfd, data, len, 0) ;
if(0==hr)
goto RE_READ ;
}
}
return hr ;
#else
//HRESULT hr = ::recv(m_sockfd, data, len, 0);
int hr = ::recv(m_sockfd, data, len, 0);

if (hr == SOCKET_ERROR)
{
return -1 ;
}
return hr ;
#endif
}

解决方案 »

  1.   


    else if(FD_ISSET(m_udpfd, &r_fdset) )
    {
    /*检查数据是否是来自我们的gameserver*/
    hr = ::recv(m_udpfd, data, len, 0) ;
    if(0==hr)
    goto RE_READ ;
    }
    你的m_udpfd没有connect不能用recv只能用recvfrom;
      

  2.   

    tcp,udp 混合通信的问题首先,需要看协议是否支持混合通信,
       因为我们的winsock是建立在协议层次的上一层,
       
       SOCKET---- WINSOCK.DLL----TCP /IP and so on
      

  3.   

    因为在同一个端口上打开的话,服务器就可以很方便的知道client的地址很端口
      

  4.   

    可是我突然想起来,我没有考虑到lan -wan - lan的模式也就是NAT的模式:( 郁闷啊
      

  5.   

    goto RE_READ ;呵呵,很久没看到有人用goto了,真TMD爽!你用lan - lan模式调试?不会吧!难道你在两个不同的局域网里面调试?
    怎么可能呢!你说一会可以用,一会又不可以用,难道经常换机调试吗!
    其实你开两个不同的端口,在自己机上调试就可以了。