#include "stdafx.h"
#include "MySocket.h"
class CServerSocket : public CMySocket
{
public
stUserListNode GetUser(constchar* userName);
int Run();
private
UserList m_userList;
};
stUserListNode* CServerSocket::GetUser(constchar* userName)
{
for (UserList::iterator iter = m_userList; iter != m_userList.end(); ++iter)
{
if (strcmp((*iter)->userName, userName) == 0)
return *iter;
}
throw Exception("not find this user");
}
int CServerSocket::Run()
{
try
{
m_socket = mksock(SOCK_DGRAM);
sockaddr_in local;
local.sin_family=AF_INET;
local.sin_port= htons(SERVER_PORT);
local.sin_addr.s_addr = htonl(INADDR_ANY);
int nResult=bind(m_socket,(sockaddr*)&local,sizeof(sockaddr));
if(nResult == SOCKET_ERROR)
throw Exception("bind error");
sockaddr_in sender;
stMessage recvbuf;
memset(&recvbuf,0,sizeof(stMessage));
for(;;)
{
int dwSender = sizeof(sender);
int ret = Recvfrom( (char *)&recvbuf, sizeof(stMessage)
, 0, (sockaddr *)&sender, &dwSender);
if(ret <= 0)
{
printf("recv error");
continue;
}
else
{
int messageType = recvbuf.iMessageType;
switch(messageType){
case LOGIN:
{
printf("has a user login : %s\n", recvbuf.message.loginmember.userName);
stUserListNode *currentuser = new stUserListNode();
strcpy(currentuser->userName, recvbuf.message.loginmember.userName);
currentuser->ip = ntohl(sender.sin_addr.S_un.S_addr);
currentuser->port = ntohs(sender.sin_port);
ClientList.push_back(currentuser);
int nodecount = (int)ClientList.size();
Sendto((constchar*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender
, sizeof(sender));
for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end();
++UserIterator)
{
Sendto((constchar*)(*UserIterator), sizeof(stUserListNode), 0
, (const sockaddr*)&sender, sizeof(sender));
}
break;
}
case LOGOUT:
{
printf("has a user logout : %s\n", recvbuf.message.logoutmember.userName);
UserList::iterator removeiterator = NULL;
for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end(); ++UserIterator)
{
if( strcmp( ((*UserIterator)->userName), recvbuf.message.logoutmember.userName) == 0 )
{
removeiterator = UserIterator;
break;
}
}
if(removeiterator != NULL)
ClientList.remove(*removeiterator);
break;
}
case P2PTRANS:
{
printf("%s wants to p2p %s\n",inet_ntoa(sender.sin_addr)
,recvbuf.message.translatemessage.userName);
stUserListNode node = GetUser(recvbuf.message.translatemessage.userName);
sockaddr_in remote;
remote.sin_family=AF_INET;
remote.sin_port= htons(node.port);
remote.sin_addr.s_addr = htonl(node.ip);
in_addr tmp;
tmp.S_un.S_addr = htonl(node.ip);
printf("the address is %s,and port is %d\n",inet_ntoa(tmp), node.port);
stP2PMessage transMessage;
transMessage.iMessageType = P2PSOMEONEWANTTOCALLYOU;
transMessage.iStringLen = ntohl(sender.sin_addr.S_un.S_addr);
transMessage.Port = ntohs(sender.sin_port);
Sendto((constchar*)&transMessage, sizeof(transMessage), 0
, (const sockaddr *)&remote, sizeof(remote));
break;
}
case GETALLUSER:
{
int command = GETALLUSER;
Sendto((constchar*)&command, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender));
int nodecount = (int)ClientList.size();
Sendto((constchar*)&nodecount, sizeof(int), 0, (const sockaddr*)&sender, sizeof(sender));
for(UserList::iterator UserIterator=ClientList.begin();
UserIterator!=ClientList.end();
++UserIterator)
{
Sendto((constchar*)(*UserIterator), sizeof(stUserListNode), 0
, (const sockaddr*)&sender, sizeof(sender));
}
break;
}
}
}
}
}
catch(Exception &e)
{
printf(e.GetMessage());
return 1;
}
return 0;
}
#ifndef _MESSAGE_H_
#define _MESSAGE_H_
#include <list>
usingnamespace std;
enum MSG_TYPE
{
LOGIN_MSG,
LOGOUT_MSG,
P2PTRANS_MSG,
GETUSER_MSG,
DATA_MSG
};
struct stLoginMessage
{
char userName[10];
char password[10];
};
struct stLogoutMessage
{
char userName[10];
};
struct stP2PTranslate
{
char userName[10];
};
struct stUserListNode
{
char userName[10];
unsigned int ip;
unsigned short port;
};
union MSG_BODY
{
stLoginMessage loginmember;
stLogoutMessage logoutmember;
stP2PTranslate translatemessage;
stUserListNode user;
};
struct stMessage
{
MSG_TYPE msgType;
MSG_BODY msgBody;
};
#define P2PMESSAGE 100 // 发送消息
#define P2PMESSAGEACK 101 // 收到消息的应答
#define P2PSOMEONEWANTTOCALLYOU 102 // 服务器向客户端发送的消息
#define P2PTRASH 103 // 客户端发送的打洞包,接收端应该忽略此消息
struct stP2PMessage
{
int iMessageType;
int iStringLen;
unsigned short Port;
};
(shuizhiyun) |