#pragma comment (lib,"WS2_32.LIB")
#pragma warning (disable:4786)
#include <afx.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <winsock2.h>
#include <afxsock.h>
#include <map>
#include <windows.h>
using namespace std;
struct IP_ADDRESS
{
CString tcp_ip;
UINT tcp_port;
};
map <int,IP_ADDRESS> allip;
//返回的字符串在下一个WinSock函数调用前不会释放,不是储存在栈中。
//获得本地IP地址。
char * GetLocalIp()
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
return "WSAStartup Error!";
char hostname[100];
struct hostent *addr=NULL;
gethostname(hostname,sizeof(hostname));
addr=gethostbyname(hostname);
if(!addr)
{
printf("Can't Get Local IP!\n");
return "Can't Get Local IP!";//字符串产量也不是储存在栈中。
}
struct in_addr aa;
int i=0;
for(i=0;addr->h_addr_list[i]!=NULL;i++)
{
memcpy(&aa,addr->h_addr_list[i],sizeof(aa));//获得第i本地IP,可以通过遍历获得其他的IP
//找到合适就退出,都没找到返回其他信息。
//printf("Local Ip is %s\n",inet_ntoa(aa));
break;
}
WSACleanup();
return inet_ntoa(aa);//返回合适的IP,注意在下一次调用Winsock函数时返回值的指向的对象要copy下来。
}
//三个模块,分别拥有各自的UDP端口。
//1.服务器端
//2.客户端
//3.结束线程
//首先一开始就启动客户端和服务器端线程.
//客户端线程主要负责搜寻局域网内在线的用户IP(发送一个senddataup的广播报文,端口就是服务器端口,
//该报文的发给其他主机的服务器端线程,当然也会发给本机的服务器端线程,但被我过滤了),主线程此时提示用户是否停止客户端线程。
//至于服务端线程主要是接收广播报文(其他主机客户端线程和结束线程)并处理,根据报文报告当前局域网用户的上下线情况,上线的时候还要给上线用户报告情况。
//主线程中如果用户停止了客户端线程,此时只有服务器端线程在跑,主线程提示用户是否关闭服务器端线程。
//如果客户选择关闭服务器端线程,首先先运行结束线程,结束线程主要向其他主机的服务器端发送自己下线的广播报文,然后结束服务器端线程(通过结束标志)
//还有在局域网内相互之间发送报文的还没实现,初步想法可以把客户端线程分为两部分,一部分是搜索局域网内的主机,一部分进行发数据,可以单播,也可以广播,还是发给
//服务器端端口
//服务器端在增加一个接收数据的功能,当然每个主机要保留一份当前局域网的上线名单。
class GetAllIPLan
{
SOCKET udp_s; //客户端的套接字。
SOCKET udpserver_s; //服务器端的套接字。
SOCKET udpend_s; //结束线程所用的套接字。
CFile ipfile;
//以下两个地址客户端线程与结束线程用到两个地址,服务器端线程只用到一个地址,server_address;
struct sockaddr_in client_address;
struct sockaddr_in server_address;
//服务器端线程中用于接收客户端的地址
struct sockaddr_in cur_address;
static int cur_addresslen;
//分别对应三个模块的地址初始化
void init_addressclient();
void init_addressserver();
void init_addressend();
//本地IP,及本机TCP的服务端口(用于服务器端线程响应其他主机的请求广播),
CString local_ip;
unsigned short tcp_serverport;
public:
//分别对应三个模块的线程函数。
static DWORD WINAPI ThreadProcclient(LPVOID lpParameter);
static DWORD WINAPI ThreadProcserver(LPVOID lpParameter);
static DWORD WINAPI ThreadEnd(LPVOID lpParameter);
//三个模块的实现函数
char * get_allipclient();
char * get_allipserver();
char * get_allipend();
//服务器端构造响应报文,主要是本机IP及指定的TCP端口。
void create_senddata(CString & sendtmp);
//标志着是否人工关闭服务器端线程;
static BOOL stop_flag_client;
//标志着服务器端线程是否已经关闭
static BOOL stop_flag_server;
//标志结束线程已经启动,此时服务器端不在处理一般报文,只处理报告请求的报文,此时服务器端线程马上也要结束。
static BOOL End_flag_server;
//三个模块对应的UDP端口
static unsigned short udpall_clientport;
static unsigned short udpall_serverport;
static unsigned short end_port;
//要发送的TCP端口,及服务器端发送数据的长度。
static unsigned short tcpcur_serverport;
static int recvlen;
//主机上线 下线对应的广播报文的内容
static char * senddataup;
static char * senddatadown;
};
BOOL GetAllIPLan :: stop_flag_client=FALSE;
BOOL GetAllIPLan :: stop_flag_server=FALSE;
BOOL GetAllIPLan :: End_flag_server=FALSE;
unsigned short GetAllIPLan :: udpall_clientport=4564;
unsigned short GetAllIPLan :: udpall_serverport=3322;
unsigned short GetAllIPLan :: end_port=5553;
unsigned short GetAllIPLan :: tcpcur_serverport=4545;
int GetAllIPLan:: recvlen=100;
int GetAllIPLan :: cur_addresslen=sizeof(sockaddr);
char * GetAllIPLan :: senddataup ="I Am OnLine!";
char * GetAllIPLan :: senddatadown ="I AM OffLine!";
//服务器端线程
DWORD WINAPI GetAllIPLan :: ThreadProcserver(LPVOID lpParameter)
{
GetAllIPLan task;
char * result=task.get_allipserver();
printf("The server Task Result is %s End.\n",result);
return 0;
}
void GetAllIPLan ::create_senddata(CString & sendtmp)
{
BYTE *s=NULL;
s=new BYTE[7];
DWORD nip=inet_addr(local_ip.GetBuffer(0));
memcpy(s,&nip,sizeof(nip));
WORD nport=htons(tcp_serverport);
memcpy(s+4,&nport,sizeof(nport));
s[6]='\0';
sendtmp=s;
}
void GetAllIPLan :: init_addressserver()
{
local_ip=GetLocalIp();
memset(&client_address,0,sizeof(client_address));
memset(&server_address,0,sizeof(server_address));
server_address.sin_family=AF_INET;
server_address.sin_port=htons(udpall_serverport);
server_address.sin_addr.S_un.S_addr=inet_addr(local_ip.GetBuffer(0));
//server_address.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
tcp_serverport=tcpcur_serverport;
}
char * GetAllIPLan :: get_allipserver()
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
return "WSAStartup Error!";
udpserver_s=socket(AF_INET,SOCK_DGRAM,0);
if(udpserver_s==INVALID_SOCKET)
return "INVALID_SOCKET!";
init_addressserver();
if(bind(udpserver_s,(struct sockaddr *)&server_address,sizeof(sockaddr))==SOCKET_ERROR)
return "Bind Error!";
fd_set rset;
struct timeval tt;
tt.tv_sec=2;
tt.tv_usec=0;
char *rbuf=NULL;
while(!stop_flag_server)
{
FD_ZERO(&rset);
FD_SET(udpserver_s,&rset);
int ret=select(0,&rset,NULL,NULL,&tt);
if(ret==0||ret==SOCKET_ERROR)
continue;
if(ret>0&&FD_ISSET(udpserver_s,&rset))
{
rbuf=new char[recvlen+1];
memset(rbuf,0,recvlen+1);
if(recvfrom(udpserver_s,rbuf,recvlen,0,(struct sockaddr *)&cur_address,&cur_addresslen)==SOCKET_ERROR)
continue;
CString tmp1(inet_ntoa(cur_address.sin_addr));
CString tmp2(inet_ntoa(server_address.sin_addr));
//AfxMessageBox(tmp1+" "+tmp2);
if(tmp1==tmp2)
{
continue;
}
CString sendtmp;
if(strcmp(rbuf,senddataup)==0&&!End_flag_server)
{
create_senddata(sendtmp);
sendto(udpserver_s,sendtmp.GetBuffer(0),sendtmp.GetLength(),0,(struct sockaddr *)&cur_address,sizeof(sockaddr));
printf("%s is Online Just!\n",inet_ntoa(cur_address.sin_addr));
}
if(strcmp(rbuf,senddatadown)==0)
{
printf("%s is OffLine Now!\n",inet_ntoa(cur_address.sin_addr));
}
}
}
closesocket(udpserver_s);
return "Sussess!";
}
// 客户端线程
DWORD WINAPI GetAllIPLan :: ThreadProcclient(LPVOID lpParameter)
{
GetAllIPLan task;
char * result=task.get_allipclient();
printf("The Client Task Result is %s End.\n",result);
return 0;
}
void GetAllIPLan :: init_addressclient()
{
local_ip=GetLocalIp();
memset(&client_address,0,sizeof(client_address));
memset(&server_address,0,sizeof(server_address));
client_address.sin_family=AF_INET;
client_address.sin_port=htons(udpall_clientport);
client_address.sin_addr.S_un.S_addr=inet_addr(local_ip.GetBuffer(0));
//client_address.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
server_address.sin_family=AF_INET;
server_address.sin_port=htons(udpall_serverport);
server_address.sin_addr.S_un.S_addr=inet_addr("255.255.255.255");
}
char * GetAllIPLan :: get_allipclient()
{
allip.clear();
WSADATA wsaData;
if(WSAStartup(
基于UDP的局域网内上下线通告
需积分: 10 49 浏览量
2012-07-23
23:19:50
上传
评论
收藏 12KB RAR 举报
唳天杰
- 粉丝: 1
- 资源: 17