📄 chatnet.cpp
字号:
// Chatnet.cpp
// CChatnet implementation file
#include "chatnet.h"
#include "string.h"
#include "resource.h"
CChatNet::CChatNet()
{
}
/* Lists returns a pointer to the address list */
CAddrList* CChatNet::GetAddressList()
{
return m_AddrList;
}
/* initializes the network and binds to the protocol, sets up the messaging,
gets the user name, sets the address list and sets the channel to 1 */
BOOL CChatNet::InitNetwork(HWND hWnd)
{
if(!InitNet())
{
TRACE("Failed to activate Network\n");
return FALSE;
}
if(!SetProtocol(hWnd))
{
TRACE("Failed to set protocol\n");
return FALSE;
}
CAddr* MyAddr = new CAddr;
if(MyAddr == NULL)
{
return FALSE;
}
m_AddrList = new CAddrList;
m_AddrList->AddHead(MyAddr);
m_Channel = 1;
return TRUE;
}
/* sends a packet greeting a new user who just entered the IPC chat world.
the user name is then added to the user list */
BOOL CChatNet::WelcomeUser(LPSTR Name,LPSTR IpAddr, CHATPACKET Message)
{
CAddr *addr = new CAddr;
if(addr == NULL)
{
return FALSE;
}
SendChatPacket(IpAddr, Name, REPLYBROADCAST,NULL);
addr->SetAddress(Message.Name,IpAddr);
if(!Duplicate(addr))
m_AddrList->Insert(addr);
else
delete [] addr;
return TRUE;
}
/* This adds a user who just enetered the net to the usernet */
BOOL CChatNet::ReplyBroadcast(LPSTR Name,LPSTR IpAddr, CHATPACKET Message)
{
CAddr *addr = new CAddr;
if(addr == NULL)
{
return FALSE;
}
addr->SetAddress(Message.Name,IpAddr);
if(!Duplicate(addr))
{
m_AddrList->Insert(addr);
}
else
delete [] addr;
return TRUE;
}
/* searches to see if this address structure already exists in the user list */
BOOL CChatNet::Duplicate(CAddr *myAddr)
{
int counter = 0;
CAddr *Addr;
POSITION list;
list = m_AddrList->GetHeadPosition();
Addr = m_AddrList->GetNext(list);
counter = m_AddrList->GetCount();
if(counter>1)
while(list != NULL)
{
Addr = m_AddrList->GetNext(list);
if((strcmpi(myAddr->m_Name, Addr->m_Name) == 0) |
(strcmpi(myAddr->m_Address,Addr->m_Address) == 0))
return TRUE;
}
return FALSE;
}
/* sends a packet to alert the other workstations that our user name has changed */
BOOL CChatNet::NameUpdate(LPSTR IpAddr, CHATPACKET Message)
{
int counter = 0;
CAddr *Addr;
POSITION list;
list = m_AddrList->GetHeadPosition();
Addr = m_AddrList->GetNext(list);
counter = m_AddrList->GetCount();
if(counter>1)
while(list != NULL)
{
Addr = m_AddrList->GetNext(list);
if(lstrcmpi(IpAddr,Addr->m_Address) == 0)
{
lstrcpy(Addr->m_Name,Message.Name);
return TRUE;
}
}
return FALSE;
}
/* Deletes an address entry from the user entry */
BOOL CChatNet::DeleteUser(LPSTR IpAddr, CHATPACKET Message)
{
int counter = 0;
CAddr *Addr;
POSITION list,oldlist;
list = m_AddrList->GetHeadPosition();
Addr = m_AddrList->GetNext(list);
counter = m_AddrList->GetCount();
oldlist = list;
if(counter>1)
while(list != NULL)
{
Addr = m_AddrList->GetNext(list);
if(lstrcmpi(IpAddr,Addr->m_Address) == 0)
{
m_AddrList->RemoveAt(oldlist);
delete Addr;
return TRUE;
}
oldlist = list;
}
return FALSE;
}
/* changes the channel to the user selected channel */
void CChatNet::SetChannel(UINT Channel)
{
m_Channel = Channel;
}
/* attaches the application to the winsock.dll,
determines if the winsock.dll is a valid version,
and makes sure that there are enough sockets available */
BOOL CChatNet::InitNet(void)
{
if(WSAStartup(SOCKET_VERSION, &m_wsaData))
{
TRACE("Couldn't find the winsock.dll\n");
return FALSE;
}
if(m_wsaData.wVersion < SOCKET_VERSION)
{
TRACE("Winsock too old a rev\n");
return FALSE;
}
if(m_wsaData.iMaxSockets < SOCKETS)
{
TRACE("Not enough sockets available\n");
return FALSE;
}
return TRUE;
}
/* gracefully closes the winsock.dll and shuts down the network */
BOOL CChatNet::CloseNet(void)
{
closesocket(m_Socket);
ClearList();
return TRUE;
}
/* sets the protocol to communicate to the network with,
sets the message handler, activates the socket, and binds the
protocol to the socket */
BOOL CChatNet::SetProtocol(HWND hWnd)
{
m_Socket=socket(PF_INET,SOCK_DGRAM,0);
if(m_Socket == INVALID_SOCKET)
{
TRACE("Cannot snag socket\n");
return FALSE;
}
m_station = getservbyname("echo","udp");
m_station->s_port = htons(IPC_PORT);
if(m_station == NULL)
{
TRACE("Can't get service port address\n");
return FALSE;
}
source_addr.sin_family = AF_INET;
source_addr.sin_addr.s_addr = INADDR_ANY;
source_addr.sin_port = m_station->s_port;
if(bind(m_Socket, (LPSOCKADDR) &source_addr, sizeof(source_addr)) == SOCKET_ERROR)
{
TRACE("Cannot bind to socket\n");
return FALSE;
}
if((WSAAsyncSelect(m_Socket,hWnd,SOCKET_MESSAGE, FD_READ | FD_WRITE)) ==
SOCKET_ERROR)
{
TRACE("Unable to set wsaasync\n");
return FALSE;
}
return TRUE;
}
/* returns the size of a message */
UINT CChatNet::MessageLen(void)
{
return sizeof CHATPACKET;
}
/* receives a chat packet, call only if there really
is data waiting on the socket */
UINT CChatNet::RecChatPacket(LPSTR *lpstrSourceAddress,CHATPACKET *Message)
{
int incoming;
SOCKADDR_IN inaddr;
int addrlen = sizeof(inaddr);
incoming = recvfrom(m_Socket,(char *) Message, MessageLen(),
0, (PSOCKADDR) &inaddr,&addrlen);
*lpstrSourceAddress = inet_ntoa(inaddr.sin_addr);
if(incoming == -1)
{
incoming = 0;
incoming = WSAGetLastError() + 2000;
}
return incoming;
}
/* returns the last network event message */
WORD CChatNet::NetEvent(LPARAM lParam)
{
return WSAGETSELECTEVENT(lParam);
}
/* calculates the correct broadcast address based upon the workstations
ip address */
BOOL CChatNet::SendBroadcast(LPSTR UserName)
{
int buflen = 50;
LPHOSTENT MyHost;
char *buf = new char[100];
UINT myerror;
if ((myerror = gethostname(buf,buflen)) == 0)
{
MyHost = gethostbyname(buf);
}
else
{
myerror = WSAGetLastError();
return FALSE;
}
if (MyHost==NULL)
return FALSE;
unsigned char octet[4];
octet[0] = MyHost->h_addr[0];
if(octet[0] < 191)
{
octet[1] = MyHost->h_addr[1];
octet[2] = '\xff';
}
if(octet[0] < 127)
octet[1] = '\xff';
octet[3] = '\xff';
sprintf(buf,"%d.%d.%d.%d",octet[0],octet[1],octet[2],octet[3]);
if((SendChatPacket(buf,UserName, BROADCAST,NULL)) > 12000)
{
delete [] buf;
return FALSE;
}
delete [] buf;
return TRUE;
}
BOOL CChatNet::SendListPacket( LPCSTR UserName, UINT Mode, LPSTR Message)
{
int counter = 0;
CAddr *Addr;
POSITION list;
list = m_AddrList->GetHeadPosition();
Addr = m_AddrList->GetNext(list);
counter = m_AddrList->GetCount();
if(counter)
while(list != NULL)
{
Addr = m_AddrList->GetNext(list);
SendChatPacket(Addr->m_Address,UserName, Mode, Message);
}
return TRUE;
}
UINT CChatNet::SendChatPacket(LPCSTR lpstrDestination, LPCSTR UserName, UINT Mode, LPSTR Message)
{
CHATPACKET CP;
CString Mesg;
lstrcpy(CP.Name, UserName);
CP.Mode = Mode;
CP.Channel = m_Channel;
switch(Mode)
{
case BROADCAST:
Mesg.LoadString(IDS_ENTERING);
lstrcpy(CP.Message,Mesg.GetBuffer(Mesg.GetLength()));
break;
case REPLYBROADCAST:
Mesg.LoadString(IDS_REPLYBROADCAST);
lstrcpy(CP.Message,Mesg.GetBuffer(Mesg.GetLength()));
break;
case NAMEUPDATE:
Mesg.LoadString(IDS_NAMECHANGE);
lstrcpy(CP.Message,Mesg.GetBuffer(Mesg.GetLength()));
break;
case LEAVINGGROUP:
Mesg.LoadString(IDS_LEAVINGGROUP);
strcpy(CP.Message,Mesg.GetBuffer(Mesg.GetLength()));
break;
case MESSAGE:
lstrcpy(CP.Message,Message);
break;
}
CP.MessageLen = strlen(CP.Message);
SOCKADDR_IN dest_addr;
dest_addr.sin_family = AF_INET;
dest_addr.sin_addr.s_addr = inet_addr(lpstrDestination);
dest_addr.sin_port = m_station->s_port;
return sendto(m_Socket, (char *) &CP,MessageLen(),0,
(PSOCKADDR) &dest_addr,sizeof(dest_addr));
}
BOOL CChatNet::ClearList(void)
{
int counter = 0;
CAddr *Addr;
POSITION list,oldlist;
list = m_AddrList->GetHeadPosition();
Addr = m_AddrList->GetNext(list);
counter = m_AddrList->GetCount();
oldlist = list;
while(list != NULL)
{
Addr = m_AddrList->GetNext(list);
m_AddrList->RemoveAt(oldlist);
oldlist = list;
delete Addr;
}
delete m_AddrList;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -