通过多播实现局域网上线用户列表 c++实现

        多人在局域网上线,实现用户列表的步骤。

1、程序启动(初始化),单独只有自己。

2、发送广播,给其它用户。

3、接收其它用户发送的信息。

4、更新自己的用户列表

为了简化程序,用控制台实现,用户列表用字符串形式显示。

类 MultiSock 实现,主程序调用

头文件MultiSock.h

#include <list>
using namespace std;
#pragma comment(lib,"WS2_32")
struct hostinfo
{
string hostip;
string hostname;
};
class MultiSock
{
public:
MultiSock(void);
~MultiSock(void);
DWORD m_dwMultiAddr;
USHORT m_port;
SOCKET s;
sockaddr_in si;
hostinfo  m_host; 
list<string>  m_listhost; //上线主机名列表
list<string>  m_listip;   //上线主机IP列表
void RecvPacket(void);//接收广播和发送自己信息到广播组
void DisplayHost(void);//显示主机名列表
};

类实现MultiSock.cpp

#include "stdafx.h"
#include "MultiSock.h"
#include <string>
using namespace  std;


MultiSock::MultiSock(void)
{
WSADATA wsaData;
char hostname[255];
PHOSTENT hostinfo;
WORD sockVersion = MAKEWORD(2,2);

if (WSAStartup(sockVersion,&wsaData) != 0)  

  //载入动态库
{
return;
}

//获取自己本机的电脑名和IP
if (gethostname(hostname,sizeof(hostname)) == 0)
{
         if ((hostinfo = gethostbyname(hostname)) !=NULL)
         {
LPSTR ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list);
m_host.hostip=ip;
m_host.hostname=hostname;
   m_listhost.push_back(m_host.hostname);
m_listip.push_back(ip);


         }
}
s=socket(AF_INET,SOCK_DGRAM,0);


BOOL bReuse=TRUE;
setsockopt(s,SOL_SOCKET, SO_REUSEADDR,(char*)&bReuse,sizeof(BOOL));
m_dwMultiAddr=inet_addr(m_host.hostip.c_str());
m_port=4567;
//    m_dwMultiAddr=inet_addr("230.1.1.99");
si.sin_family = AF_INET;
si.sin_port = ntohs(m_port);
si.sin_addr.S_un.S_addr = INADDR_ANY;

// INADDR_ANY 监听所有IP
bind(s,(sockaddr*)&si, sizeof(si));


bool bopt=TRUE;
setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&bopt, sizeof(bopt));
int nTTL=64;
int nRet=setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,(char*)&nTTL,sizeof(nTTL));
if (nRet==SOCKET_ERROR)
{
return;
}
ip_mreq mcast;
mcast.imr_interface.S_un.S_addr=INADDR_ANY;
mcast.imr_multiaddr.S_un.S_addr=m_dwMultiAddr;
setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,(char*)&mcast,sizeof(mcast));


sockaddr_in sRemote;
sRemote.sin_family=AF_INET;
sRemote.sin_port=htons(m_port);

  //广播给所有地址
sRemote.sin_addr.S_un.S_addr=INADDR_BROADCAST;

int ret=sendto(s,m_host.hostname.c_str(),strlen(m_host.hostname.c_str()),0,(sockaddr*)&sRemote,sizeof(sRemote));
DisplayHost(); //发送后显示自己在线





}




MultiSock::~MultiSock(void)
{
sockaddr_in sRemote;
sRemote.sin_family=AF_INET;
sRemote.sin_port=htons(m_port);
sRemote.sin_addr.S_un.S_addr=INADDR_BROADCAST;
int ret=sendto(s,"Leave this party\r\n",strlen("Leave this party\r\n"),0,(sockaddr*)&sRemote,sizeof(sRemote));


ip_mreq mcast;
mcast.imr_interface.S_un.S_addr=INADDR_ANY;
mcast.imr_multiaddr.S_un.S_addr=m_dwMultiAddr;
setsockopt(s,IPPROTO_IP,IP_DROP_MEMBERSHIP,(char*)&mcast,sizeof(mcast));


int nRecvBuf=32*1024;
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
int nSendBuf=32*1024;
setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));




WSACleanup();
}


void MultiSock::RecvPacket(void)
{
MessageBox(NULL,TEXT("程序开始接收"),TEXT("接收"),MB_OK);
char buf[10280];
char err[10];
int nAddrLen = sizeof(si);
PHOSTENT  hostinfo;
while(TRUE)
{
Sleep(50);
int nRet = ::recvfrom(s,buf,sizeof(buf),0,(sockaddr*)&si,&nAddrLen);
bool bflag=false;
if (nRet != SOCKET_ERROR)
{
buf[nRet]='\0';
if ((strcmp(buf,m_host.hostname.c_str())))
{
    //列表中主机名不在加入列表,避免重复上线

                             for (list<string>::iterator l_host=m_listhost.begin();l_host!=m_listhost.end();++l_host)
{
bflag=false;
if (strcmp(buf,l_host->c_str()))
{
bflag=true;
}
}
if (bflag)
{
m_listhost.push_back(buf);


if (gethostname(buf,sizeof(buf)) == 0)
{
if ((hostinfo = gethostbyname(buf)) !=NULL)
{
 LPSTR ip = inet_ntoa(*(struct in_addr *)*hostinfo->h_addr_list);
 m_listip.push_back(ip);
     m_dwMultiAddr=inet_addr(ip);
     sockaddr_in sRemote;
     sRemote.sin_family=AF_INET;
     sRemote.sin_port=htons(m_port);
     sRemote.sin_addr.S_un.S_addr=INADDR_BROADCAST;

                                             //发送自己的主机名给其它人员
    int ret=sendto(s,m_host.hostname.c_str(),strlen(m_host.hostname.c_str()),0,(sockaddr*)&sRemote,sizeof(sRemote));
}
}
DisplayHost(); //有新加入的成员重新刷新列表
}

}




// MessageBox(NULL,buf,TEXT("數據"),MB_OK);

}
else
{
int n=::WSAGetLastError();
itoa(n,err,10);
MessageBox(NULL,err,TEXT("數據"),MB_OK);
break;
}
}


}

//显示列表
void MultiSock::DisplayHost(void)
{
string display;
for (list<string>::iterator l_host=m_listhost.begin();l_host!=m_listhost.end();++l_host)
{
display.append(*l_host);
}
MessageBox(NULL,display.c_str(),TEXT("在線"),MB_OK);
}

主程序main.cpp

#include "stdafx.h"
#include "MultiSock.h"


int _tmain(int argc, _TCHAR* argv[])
{
MultiSock mySock;
mySock.RecvPacket();
getchar();
return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值