查看單個文章
舊 2005-06-15, 05:27 AM   #6 (permalink)
psac
榮譽會員
 
psac 的頭像
榮譽勳章
UID - 3662
在線等級: 級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時
註冊日期: 2002-12-07
住址: 木柵市立動物園
文章: 17381
現金: 5253 金幣
資產: 33853 金幣
預設

// 登入到服務端後,接收服務端發來的已經登入的用戶的訊息
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;
}
}

void OutputUsage()
{
cout<<"You can input you command:\n"
<<"Command Type:\"send\",\"exit\",\"getu\"\n"
<<"Example : send Username Message\n"
<<" exit\n"
<<" getu\n"
<<endl;
}

/* 這是主要的函數:傳送一個消息給某個用戶(C)
*流程:直接向某個用戶的外網IP傳送消息,如果此前沒有聯係過
* 那麼此消息將無法傳送,傳送端等待超時。
* 超時後,傳送端將傳送一個請求訊息到服務端,
* 要求服務端傳送給客戶C一個請求,請求C給本地機傳送打洞消息
* 以上流程將重複MAXRETRY次
*/
bool SendMessageTo(char *UserName, char *Message)
{
char realmessage[256];
unsigned int UserIP;
unsigned short UserPort;
bool FindUser = false;
for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end();
++UserIterator)
{
if( strcmp( ((*UserIterator)->userName), UserName) == 0 )
{
UserIP = (*UserIterator)->ip;
UserPort = (*UserIterator)->port;
FindUser = true;
}
}

if(!FindUser)
return false;

strcpy(realmessage, Message);
for(int i=0;i<MAXRETRY;i++)
{
RecvedACK = false;

sockaddr_in remote;
remote.sin_addr.S_un.S_addr = htonl(UserIP);
remote.sin_family = AF_INET;
remote.sin_port = htons(UserPort);
stP2PMessage MessageHead;
MessageHead.iMessageType = P2PMESSAGE;
MessageHead.iStringLen = (int)strlen(realmessage)+1;
int isend = sendto(PrimaryUDP, (const char *)&MessageHead, sizeof(MessageHead), 0, (const sockaddr*)&remote, sizeof(remote));
isend = sendto(PrimaryUDP, (const char *)&realmessage, MessageHead.iStringLen, 0, (const sockaddr*)&remote, sizeof(remote));

// 等待接收執行緒將此標記修改
for(int j=0;j<10;j++)
{
if(RecvedACK)
return true;
else
Sleep(300);
}

// 沒有接收到目標主機的回應,認為目標主機的連接阜映射沒有
// 開啟,那麼傳送請求訊息給伺服器,要伺服器告訴目標主機
// 開啟映射連接阜(UDP打洞)
__________________
http://bbsimg.qianlong.com/upload/01/08/29/68/1082968_1136014649812.gif
psac 目前離線  
送花文章: 3, 收花文章: 1631 篇, 收花: 3205 次