我的ip为内网,我找了台有公网IP的机器运行服务器程序,
我的简短连接代码如下:
客户端程序:
......
}
void ConnectToServer(SOCKET sock,char *username, char *serverip)
{
sockaddr_in remote;
remote.sin_addr.S_un.S_addr = inet_addr(serverip);
remote.sin_family = AF_INET;
remote.sin_port = htons(SERVER_PORT);
stMessage sendbuf;
sendbuf.iMessageType = LOGIN;//登陆协议标志
strncpy(sendbuf.message.loginmember.userName, username, 20);
int num=sendto(sock, (const char*)&sendbuf, sizeof(sendbuf), 0, (const sockaddr*)&remote,sizeof(remote));
if(num==SOCKET_ERROR )
{
             printf("数据发送失败\n");
             return;
        }
int usercount;
int fromlen = sizeof(remote);
int iread = recvfrom(sock, (char *)&usercount, sizeof(int), 0, (sockaddr *)&remote, &fromlen);
if(iread<=0)
{
            printf("数据接收失败\n");
            return;
        }
// 登录到服务端后,接收服务端发来的已经登录的用户的信息
cout<<"Have "<<usercount<<" users logined server:"<<endl;
for(int i = 0;i<usercount;i++)
{
stUserListNode *node = new stUserListNode;
recvfrom(sock, (char*)node, sizeof(stUserListNode), 0, (sockaddr *)&remote,&fromlen);
ClientList.push_back(node);
cout<<"Username:"<<node->userName<<endl;
in_addr tmp;
tmp.S_un.S_addr = htonl(node->ip);
cout<<"UserIP:"<<inet_ntoa(tmp)<<endl;
cout<<"UserPort:"<<node->port<<endl;
cout<<""<<endl;
}
}
int main(int argc, char* argv[])
{
WSADATA wsaData;
        sockaddr_in addr;
        char ServerIP[20],UserName[20];
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
             printf("Windows sockets 2.2 startup");
             return 0;
        }
        SOCKET sock = socket(AF_INET, SOCLK_DGRAM, 0);
if (sock < 0)
{
             printf("create socket error");
             return 0;
}
addr.sin_addr.S_un.S_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = 0;
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)

               printf("BindSock error");
               return 0;
        }
        cout<<"Please input server ip:";
cin>>ServerIP;
cout<<"Please input your name:";
cin>>UserName;
ConnectToServer(PrimaryUDP, UserName, ServerIP);
}服务器程序:int main(int argc, char* argv[])
{
        WSADATA wsaData;
        sockaddr_in addr;
        char ServerIP[20],UserName[20];
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
             return 0;
        }
        SOCKET sock = socket(AF_INET, SOCLK_DGRAM, 0);
if (sock < 0)
{
             return 0;
}
addr.sin_addr.S_un.S_addr = INADDR_ANY;
addr.sin_family = AF_INET;
addr.sin_port = 0;
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)

               return 0;
        }
        sockaddr_in sender;
stMessage recvbuf;//客户端与服务器的通信协议
        memset(&recvbuf,0,sizeof(stMessage));
        for(;;)
{
              printf("开始接受数据\n");
      int dwSender = sizeof(sender);
      int ret = recvfrom(PrimaryUDP, (char *)&recvbuf, sizeof(stMessage), 0, (sockaddr *)&sender, &dwSender);
if(ret <= 0)
{
printf("接受数据失败!");
continue;
}
else
{ printf("成功接受数据长度:%d\n",ret);
int messageType = recvbuf.iMessageType;
switch(messageType)
                       {                        case LOGIN:
{
//  将这个用户的信息记录到用户列表中
printf("新用户到来 : %s\n", recvbuf.message.loginmember.userName);
printf("新用户IP地址为:%s,端口为:%d\n",inet_ntoa(sender.sin_addr),ntohs(sender.sin_port));
                         .....;
                         break;
                        }
                        ..........;
                        }
             }
}附:
#define LOGIN 1
stMessage结构:
#define SERVER_PORT 2280// Client登录时向服务器发送的消息
struct stLoginMessage
{
char userName[20];
};// Client注销时发送的消息
struct stLogoutMessage
{
char userName[20];
};// Client向服务器请求另外一个Client(userName)向自己方向发送UDP打洞消息
struct stP2PTranslate
{
char userName[20];
};// Client向服务器发送的消息格式
struct stMessage
{
int iMessageType;
union _message
{
stLoginMessage loginmember;
stLogoutMessage logoutmember;
stP2PTranslate translatemessage;
}message;
};疑问:我连接公网服务器时:两边都好象没反映,程序就停在那了(从recvfrom()开始程序就好象不能网下执行了,客户端与服务器都是这样),我想recvfrom是阻塞函数,停在这里就是网络上根本没数据到达,但我看了这个程序好几变,但没发现问题所在,我觉得应该有数据过来呀!该程序在局域网能成功测试,请教高手解决!

解决方案 »

  1.   

    首先要保证你的通讯链路是通的,ping一下你的公网ip
    另外你的内网的路由器能够保证把你的udp包路由到公网上,这是最大的一个问题。
      

  2.   

    我是校园网用户,链路是通的,至于内网的路由器能够保证把udp包路由到公网上我不知道,怎样去测试?但我想我上网登陆服务器时不是可以吗,为什么登陆自己搭建的简单服务器就不行?
      

  3.   

    小网络程序 用sockmon 抓包 一看便知
      

  4.   

    sockaddr改为大写,在设置端口时,对其进行格式转换一下addr.sin_port = htons(0); addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);再试一下!
      

  5.   


    这东西象是什么UDP打洞的测试代码.运行环境是要指定的那类型网关以及客户端要在两个不同网关的内网系统中运行.自己检查是哪个问题吧.