这是一个用VC++写的P2P聊天程序,客户端连接服务器的时候连接不上(这个服务器只是记录着连接服务器的客户端的信息,与C/S结构的服务器不同),哪位好心人能帮忙看一下,哪里出错了???万分感谢了!!!!服务器的部分代码:
BOOL CP2PServerDlg::OnInitDialog()
{
.................................
// TODO: Add extra initialization here
//创建套接字,绑定到本地端口
         g_s=::WSASocket(AF_INET,SOCK_DGRAM,IPPROTO_UDP,NULL,0,WSA_FLAG_OVERLAPPED);
         sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(SERVER_PORT);
sin.sin_addr.S_un.S_addr=INADDR_ANY;
if(::bind(g_s,(LPSOCKADDR)&sin,sizeof(sin))==SOCKET_ERROR)
{
     MessageBox("绑定套接字失败!");
 return;
}
//下面这段代码用来显示服务器绑定的终端
         ::gethostname(szHost,256);
hostent *pHost=::gethostbyname(szHost);
for(int i=0;;i++)
{
char *p=pHost->h_addr_list[i];
if(p==NULL) 
break;
memcpy(&addr.S_un.S_addr,p,pHost->h_length);
SetDlgItemText(IDC_EDIT1,::inet_ntoa(addr));
SetDlgItemText(IDC_EDIT2,"4567");
}
SetDlgItemText(IDC_EDIT3,"P2P服务器连接成功!\n\n");
::InitializeCriticalSection(&g_PeerListLock);         PARAM *pParam=new PARAM;
pParam->socket=g_s;
pParam->hwnd=m_hWnd;
         s_hThread=::CreateThread(NULL,0,IOThreadProc,(LPVOID)pParam,0,NULL);       
return TRUE;  
}
DWORD WINAPI CP2PServerDlg::IOThreadProc(LPVOID lpParam)
{
    SOCKET socket=((PARAM*)lpParam)->socket;
    HWND  hwnd=((PARAM*)lpParam)->hwnd;
    char buff[MAX_PACKET_SIZE];
    sockaddr_in remoteAddr;
    int nRecv,nAddrLen=sizeof(remoteAddr);
    while(TRUE)
{
nRecv=::recvfrom(socket,buff,MAX_PACKET_SIZE,0,(sockaddr*)&remoteAddr,&nAddrLen);
if(nRecv==SOCKET_ERROR)
               break;
if(nRecv<sizeof(CP2PMessage))
               break;
//防止用户发送错误的用户名
         CP2PMessage *pMsg=(CP2PMessage*)buff;
pMsg->peer.szUserName[MAX_USERNAME]='\0';
switch(pMsg->nMessageType)
{
   case USERLOGIN:
{
pMsg->peer.addr[pMsg->peer.AddrNum].dwIp=remoteAddr.sin_addr.S_un.S_addr;
pMsg->peer.addr[pMsg->peer.AddrNum].nPort=ntohs(remoteAddr.sin_port);
pMsg->peer.AddrNum++;
pMsg->peer.dwLastActiveTime=::GetTickCount();
::EnterCriticalSection(&g_PeerListLock);
BOOL bOK=g_PeerList.AddAPeer(&pMsg->peer);
::LeaveCriticalSection(&g_PeerListLock);
char tempBuf[200];
if(bOK)
 {
    pMsg->nMessageType=USERLOGACK;
    ::sendto(socket,(char*)pMsg,sizeof(CP2PMessage),0,(sockaddr*)&remoteAddr,sizeof(remoteAddr));
           sprintf(tempBuf,"登录服务器成功");
 ::PostMessage(hwnd,WM_LOGIN,0,(LPARAM)tempBuf);
           }
}
break;
case USERLOGOUT:
{
::EnterCriticalSection(&g_PeerListLock);
g_PeerList.DeleteAPeer(pMsg->peer.szUserName);
::LeaveCriticalSection(&g_PeerListLock);
//SetDlgItemText(IDC_EDIT3,"有个用户退出");
}
break;

    
}        
}
               return 0;
}void CP2PServerDlg::OnLogin(WPARAM wParam,LPARAM lParam)
{
CString str=(char*)lParam;
CString strTemp;
GetDlgItemText(IDC_EDIT3,strTemp);
str+="\r\n";
str+=strTemp;
SetDlgItemText(IDC_EDIT3,str);}客户端的部分代码:
DWORD WINAPI CP2PClientDlg::RecvThreadProc(LPVOID lpParam)
{
CP2PClientDlg *pThis=(CP2PClientDlg*)lpParam;
char buff[MAX_PACKET_SIZE];
sockaddr_in remoteAddr;
int nAddrLen=sizeof(remoteAddr);
WSABUF wsaBuf;
wsaBuf.buf=buff;
wsaBuf.len=MAX_PACKET_SIZE;
//接收处理到来的消息
while(TRUE)
{
DWORD dwRecv,dwFlags=0;
int nRet=::WSARecvFrom(pThis->m_s,&wsaBuf,1,&dwRecv,&dwFlags,(sockaddr*)                   &remoteAddr,&nAddrLen,&pThis->m_ol,NULL);
if(nRet==SOCKET_ERROR&&::WSAGetLastError()==WSA_IO_PENDING)
{
::WSAGetOverlappedResult(pThis->m_s,&pThis->m_ol,&dwRecv,TRUE,&dwFlags); }
//首先查看是否要退出
if(pThis->m_bThreadExit) break;
//调用HandleIO函数来处理这个消息
pThis->HandleIO(buff,dwRecv,(sockaddr*)&remoteAddr,nAddrLen);
}
return 0;}void CP2PClientDlg::HandleIO(char *pBuf, int nBufLen, sockaddr *addr, int nAddrLen)
{
CP2PMessage *pMsg=(CP2PMessage*)pBuf;
if(nBufLen<sizeof(CP2PMessage))
return;
switch(pMsg->nMessageType)
{
case USERLOGACK:    //接收到服务器发来的登录确认
{
memcpy(&m_LocalPeer,&pMsg->peer,sizeof(PEER_INFO));
m_bLogin=TRUE;
}
break;
         ......
}
}
void CP2PClientDlg::OnBtnLink() 
{
// TODO: Add your control notification handler code here

char  szServerIp[20];
char  szUserName[MAX_USERNAME];
GetDlgItem(IDC_EDIT_SERVERIP)->GetWindowText(szServerIp,20);
GetDlgItem(IDC_EDIT_USERNAME)->GetWindowText(szUserName,15);        if(m_bLogin||strlen((char*)szUserName)>MAX_USERNAME-1)
MessageBox("连接失败");
//保存参数
m_dwServerIp=::inet_addr((char*)szServerIp);
strncpy(m_LocalPeer.szUserName,(char*)szUserName,strlen((char*)szUserName));
//服务器名称
sockaddr_in serverAddr;
        serverAddr.sin_family=AF_INET;
serverAddr.sin_addr.S_un.S_addr=m_dwServerIp;
serverAddr.sin_port=htons(SERVER_PORT);

//向服务发送本用户信息
CP2PMessage logMsg;
logMsg.nMessageType=USERLOGIN;
memcpy(&logMsg.peer,&m_LocalPeer,sizeof(PEER_INFO));
for(int i=0;i<MAX_TRY_NUMBER;i++)
{
::sendto(m_s,(char*)&logMsg,sizeof(logMsg),0,(sockaddr*)&serverAddr,sizeof(serverAddr));
for(int j=0;j<10;j++)
{
if(m_bLogin)
return ;
::Sleep(300);
}

}
return ;
}

解决方案 »

  1.   

    BOOL CP2PClientDlg::OnInitDialog()
    {
    ......    
            if(m_s!=INVALID_SOCKET)
    return FALSE;
    //创建用于P2P通信的UDP套接字,进行绑定
    m_s=::WSASocket(AF_INET,SOCK_DGRAM,IPPROTO_UDP,NULL,0,WSA_FLAG_OVERLAPPED);
    sockaddr_in localAddr;
    localAddr.sin_family=AF_INET;
    localAddr.sin_port=htons(SERVER_PORT);
    localAddr.sin_addr.S_un.S_addr=INADDR_ANY;
    if(::bind(m_s,(LPSOCKADDR)&localAddr,sizeof(localAddr))==SOCKET_ERROR)
    {
    ::closesocket(m_s);
    m_s=INVALID_SOCKET;
    return FALSE;
    }

    int nLen=sizeof(localAddr);
    ::getsockname(m_s,(sockaddr*)&localAddr,&nLen); //获取本地机器的IP地址,得到当前用户的私有终端
    char szHost[256];
    ::gethostname(szHost,256);
    hostent *pHost=::gethostbyname(szHost);
    memset(&m_LocalPeer,0,sizeof(m_LocalPeer));
    for(int i=0;i<MAX_ADDR_NUMBER-1;i++)
    {
    char *p=pHost->h_addr_list[i];
    if(p==NULL)
    break;
    memcpy(&m_LocalPeer.addr[i].dwIp,&p,pHost->h_length);
    m_LocalPeer.addr[i].nPort=SERVER_PORT;
    m_LocalPeer.AddrNum++;
    }
    //创建接收服务线程
    m_bThreadExit=FALSE;
            c_hThread=::CreateThread(NULL,0,RecvThreadProc,this,0,NULL);
    return TRUE;  // return TRUE  unless you set the focus to a control
    }
      

  2.   

    不知道你的listen()函数在何方?
      

  3.   

    udp的。直接向服务器发数据就好了。
      

  4.   

    建议你下个抓包工具 ethereal,然后启动程序,看看你能不能发数据包,如果不能,那就是客户端有问题。然后加断点,看看每一步调用的mfc函数是否成功,确定问题在什么位置。
      

  5.   

    主要是连接的地方出问题 SOCKET有没初始化 WORD wVersionRequested;
    WSADATA wsaData;
    int err;
    wVersionRequested = MAKEWORD( 1, 1 );
    int nRet;
    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 ) {
    return 0;
    }

    if ( LOBYTE( wsaData.wVersion ) != 1 ||
            HIBYTE( wsaData.wVersion ) != 1 ) {
    WSACleanup( );
    return 0; 
    }
      

  6.   

    这个我已经初始化了,我把它放在App的InitInstance()中了。