首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

妖哥能不能帮忙看一上

2013-01-07 
妖哥能不能帮忙看一下妖哥:问一个问题,我的局域网上有一个设备,我要搜索到这台设备就要通过UDP广播发送请

妖哥能不能帮忙看一下


妖哥:问一个问题,我的局域网上有一个设备,我要搜索到这台设备就要通过UDP广播发送请求命令去查询,然后设备通过广播返回设备信息给我。
下面是我的发送命令的过程:
        int t_nRet = 0;
        SOCKET t_Socket = NULL;
        SOCKADDR_IN t_SocketAddrin;
        BOOL t_bBroadcast = TRUE;
        
        t_SocketAddrin.sin_family = AF_INET;
        t_SocketAddrin.sin_port = htons(1092);
        t_SocketAddrin.sin_addr.s_addr = inet_addr("255.255.255.255");

        char t_chMessage[113] =
        {
            0x5a,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00
        };

        t_Socket = socket(AF_INET, SOCK_DGRAM, 0);
        if(t_Socket == SOCKET_ERROR)
        {
            return;
        }

        t_nRet = setsockopt(t_Socket,SOL_SOCKET,SO_BROADCAST,(const char*)&t_bBroadcast,sizeof(BOOL));
        if(t_nRet != 0)
        {
            closesocket(t_Socket);
            return;
        }

        sendto(t_Socket, t_chMessage, 113, 0, (struct sockaddr*)&t_SocketAddrin, sizeof(SOCKADDR_IN));

        closesocket(t_Socket);

==================================================================
这里是我的接受网络中广播的代码:
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 0);


if (WSAStartup(wVersionRequested, &wsaData) != 0)
{
return 0;
}

if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 0)
{
WSACleanup();
return 0;
}

char chMessage[113] = {0};
SOCKET m_Socket;
SOCKADDR_IN m_SocketAddrIn;
SOCKADDR_IN m_SocketRemoteAddrIn;
int iRemoteAddrLen;
iRemoteAddrLen = sizeof(SOCKADDR_IN);
bool t_bBroadcast = TRUE;
int nRet;

m_Socket = socket(AF_INET,   SOCK_DGRAM,  0);
if(m_Socket == SOCKET_ERROR)
{
WSACleanup();
system("pause");
return 0;
}

m_SocketAddrIn.sin_family = AF_INET;
m_SocketAddrIn.sin_port = htons(1092);
m_SocketAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);

nRet = setsockopt(m_Socket,SOL_SOCKET,SO_BROADCAST,(char FAR *)&t_bBroadcast,sizeof(bool));
if (nRet != 0)
{
printf( "设置失败! %d\n",   WSAGetLastError());
closesocket(m_Socket);
WSACleanup();
system("pause");
return 0;
}

nRet = bind(m_Socket, (struct sockaddr*)&m_SocketAddrIn, sizeof(m_SocketAddrIn));
if (nRet == SOCKET_ERROR)
{
printf( "绑定失败! %d\n",   WSAGetLastError());
closesocket(m_Socket);
WSACleanup();
system("pause");
return 0;
}

while(1)
{
nRet = recvfrom(m_Socket, chMessage, 113, 0, (struct sockaddr*)&m_SocketRemoteAddrIn, &iRemoteAddrLen);
if(nRet == SOCKET_ERROR)
{
printf( "接受数据失败! %d\n",   WSAGetLastError());
closesocket(m_Socket);
WSACleanup();
system("pause");
return 0;
}

chMessage[nRet] = '\0';

printf( "接收数据IP地址: %s\n",inet_ntoa(m_SocketRemoteAddrIn.sin_addr));
}

closesocket(m_Socket);
WSACleanup();

system("pause");

return 0;
}

=================================================================
问题是我发送命令出去后,我的接收端接受不到设备返回的信息,而且比较奇怪的是我只能收到5次来自本机地址的我发送出去的数据。但是我用Wireshark查看数据包是可以看到设备往255.255.255.255这个地址在不停的发包。

妖哥能不能帮我看看代码这里有什么问题没?


[解决办法]
如果网络中两个主机上的应用程序要相互通信,其一要知道彼此的IP,其二要知道程序可监听的端口。因为同一主机上的程序使用网络是通过端口号来区分的。

UDP Socket的使用过程:
1.       初始化网络库

2.       创建SOCK_DGRAM类型的Socket。

3.       绑定套接字。

4.       发送、接收数据。

5.       销毁套接字。

6.       释放网络库。

广播数据包的原理:
专门用于同时向网络中所有工作站进行发送的一个地址叫做广播地址。在使用TCP/IP 协议的网络中,主机标识段host ID 为全1 的IP 地址为广播地址。如果你的IP为:192.168.1.39,子网掩码为:255.255.255.0,则广播地址为:192.168.1.255;如果IP为192.168.1.39,子网掩码为:255.255.255.192,则广播地址为:192.168.1.63。

如果只想在本网络内广播数据,只要向广播地址发送数据包即可,这种数据包可以被路由,它会经由路由器到达本网段内的所有主机,此种广播也叫直接广播;如果想在整个网络中广播数据,要向255.255.255.255发送数据包,这种数据包不会被路由,它只能到达本物理网络中的所有主机,此种广播叫有限广播。

使用UDP协议发送、接收广播包的过程。
假如我们要向192.168.0.X,子网掩码为:255.255.255.0的子网中发送广播包。

其步骤如下:

1.       初始化Winsock库。

2.       创建SOCK_DIRAM类型的Socket。

3.       设置Socket的属性允许其广播。

4.       发送数据包到192.168.0.255



5.       接收自己广播的广播包。

6.       关闭Socket

7.       释放网络库。

注意事项如下:

1.       接收方一定要知道广播方的口号,然后绑定此端口号才能正确接收。

2.       接收方的Socket不需要设置成广播属性。

3.       绑定的IP不可以使用“127.0.0.1”,可以使用真实IP地址或者INADDR_ANY。否则接收失败。


参考代码:

     #include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
//*-----------变量,数据类型宏定义-------------------
#define PORT 3387
#define MAX 255

int main(void)
{
int sockfd, ret;
int size, len;
int so_broadcast=1;
struct sockaddr_in my_con;
struct sockaddr_in cl_con;
char snd[MAX] = "123456789";
char rec[MAX];
//创建socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd < 0)
{
perror("socket error!\n");
exit(1);
}

//创建套接口
my_con.sin_family = AF_INET;
my_con.sin_port = ntohs(PORT);
my_con.sin_addr.s_addr =  inet_addr("192.168.1.255");
len = sizeof(struct sockaddr);

setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast));
//绑定套接口
if(bind(sockfd, (struct sockaddr *) &my_con, len) < 0)
{
perror("bind error!\n");
exit(1);
}
//数据传输处理
ret = sendto(sockfd, snd, strlen(snd), 0, (struct sockaddr *) &my_con, len);
if(ret < 0)
{
perror("send error!\n");
exit(1);
}
printf("发送广播数据:%s\n",snd);
size=sizeof(cl_con);
ret = recvfrom(sockfd,rec,MAX,0,(struct sockaddr *)&cl_con,&size);
rec[ret] = '\0';
printf("接收广播数据:%s\n",rec);
close(sockfd);
return 0;
}


热点排行