PS:自己对经过的坑做个总结,也许对其他读者也有用。总之各种坑emmm,有啥问题欢迎留言指教。必回!
还有,你问已经写好的可以直接用的文件?tan90°不存在的,就一丁点代码,自己写一下印象更深(滑稽)
UDP广播是不建立稳定的连接情况下 ,通过在指定网段,调用指定的端口,向该网段内所有开放此接口的设备推送消息。对于接收端来说,通过开放对应端口来进行数据的接收工作。
UDP广播存在以下的特点:一对一、一对多、不稳定、速度快等特点
项目通过验证,后述的接收端和发送端需满足以下条件,其他环境的尚未验证(欢迎大家验证共同探讨)。
#include
#include
#include
#include
#include
#include
#include
#pragma comment(lib, "ws2_32.lib")
//根据输入的CString内容推送到本地路由器所在的网段
void SendUDPSockeMessage(CString opt)
{
#if TRUE
//CString转string
std::string sz2 = CT2A(opt.GetBuffer());
//string转char*
const char* szSendToServer = sz2.c_str();
char szBuff[50] = { 0 };
WSADATA data;
WORD wVersionRequested = MAKEWORD(2, 0);
WSAStartup(wVersionRequested, &data);
//创建一个UDP的Socket,SOCK_DGRAM代表是UDP
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in addr;
addr.sin_family = AF_INET;
//创建一个端口,这个端口一般要大一点,接收端也要开放同样端口
addr.sin_port = htons(86563);
//获取本地路由器IP端
CString strIPAddr;
std::vector string_list;
{
//ip获取
char HostName[100];
gethostname(HostName, sizeof(HostName));// 获得本机主机名.
hostent* hn;
hn = gethostbyname(HostName);//根据本机主机名得到本机ip
strIPAddr=inet_ntoa(*(struct in_addr *)hn->h_addr_list[0]);//把ip换成字符串形式
int iPos=0;
CString strTmp;
strTmp=strIPAddr.Tokenize(_T("."),iPos);
while(strTmp.Trim() != _T(""))
{
string_list.push_back(strTmp);
strTmp = strIPAddr.Tokenize(_T("."),iPos);
}
int string_list_count = string_list.size();
}
//重要:必须在本地路由的255位广播,组成为XXX.XXX.XXX.255
CString ipCStr=string_list[0]+_T(".")+string_list[1]+_T(".")+string_list[2]+_T(".255");
char* ip_char = CT2A(ipCStr.GetBuffer(0));
addr.sin_addr.S_un.S_addr = inet_addr(ip_char);
//到这里准备就绪
printf("Client is setup and now trying to connect server...\n");
sockaddr_in addrServer;
int nSockAddrSize = sizeof(addrServer);
//重要:必须使用sendto
//重要:对于char* 需要用strlen获取长度;如果是char [] = {...},这要用sizeof()
sendto(s, szSendToServer, strlen(szSendToServer), 0, (sockaddr*)&addr, nSockAddrSize);
//如果有返回信息可以使用这个方法来获取,内容存在szBuff中
/*recvfrom(s, szBuff, sizeof(szBuff), 0, (sockaddr*)&addrServer, &nSockAddrSize);
printf("%s\n", szBuff); */
closesocket(s);
WSACleanup();
if (getchar()) return ;
return ;
#else
#endif
}
1、发送端在设置广播网段的时候,需要获取到本地的路由器网段,切莫使用系统自带的几个宏:INADDR_ANY、INADDR_LOOPBACK、INADDR_BROADCAST。这几个宏在路由器网段广播时无法收到消息。
2、获取到本地路由后,需要在本地路由的255位广播,组成为XXX.XXX.XXX.255
3、必须使用sendto
4、对于char 需要用strlen获取长度;如果是char [] = {…},这要用sizeof()*
5、recvfrom方法是一个堵塞线程的方式,使用的时候要注意
#include "stdafx.h"
#include
#include
#include
#pragma comment(lib, "ws2_32.lib")
int _tmain(int argc, _TCHAR* argv[])
{
//反馈内容
static const char szAnswerClient[] = "Hello! You've been connected!";
char szBuff[50] = { 0 };
WSADATA data;
WORD wVersionRequired = MAKEWORD(2, 0);
WSAStartup(wVersionRequired, &data);
//创建一个广播的Socket
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
sockaddr_in addr;
addr.sin_family = AF_INET;
//添加同样的端口
addr.sin_port = htons(86563);
//监听任何的地址推送过来的广播
addr.sin_addr.S_un.S_addr = INADDR_ANY;
//绑定端口
bind(s, (sockaddr*)&addr, sizeof(addr));
//准备接收
printf("Server is setup and now waiting for clients' request...\n");
sockaddr_in addrClient;
int nSockAddrSize = sizeof(addrClient);
//收到消息后发送内容
if (recvfrom(s, szBuff, sizeof(szBuff), 0, (sockaddr*)&addrClient, &nSockAddrSize) > 0) {
printf("There is one client(%s) connected!\n", inet_ntoa(addrClient.sin_addr));
printf("%s\n", szBuff);
//发送
sendto(s, szAnswerClient, sizeof(szAnswerClient), 0, (sockaddr*)&addrClient, nSockAddrSize);
}
closesocket(s);
WSACleanup();
if (getchar()) return 0;
return 0;
}
1、接收端在设置监听广播网段的时候,可以使用系统自带的几个宏:INADDR_ANY(任何网段)、INADDR_LOOPBACK(本地网段)、INADDR_BROADCAST(与INADDR_ANY一致)。
2、对于char 需要用strlen获取长度;如果是char [] = {…},这要用sizeof()*
3、recvfrom方法是一个堵塞线程的方式,使用的时候要注意
UDP的内容到此就完成了,代码经过测试可以使用。这里的接收端是控制台程序,先开启接收端再开启发送端发送就可以了。设置不同的strlen或者发送字节长度可以发送指定长度的内容
PS:保证同一个网段的方式很简单:两台笔记本,设置为自动IP,然后链接同一个wifi即可。