在虚拟机下进行udp广播时,需要设置网卡,一般会选择桥接模式,如果选择nat模式的话,会受到限制有可能接收不到消息,如果两个主机要进行通信的话,需要知道对方的ip和端口号才能够进行通信,在同一台主机上进行的通信主要是通过端口来进行区分的,两台不同的电脑通过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发送数据包,这种数据包不会被路由送达,它只能到达本物理网络中的所有主机,此种广播叫有限广播。
注意事项:
1. 接收方一定要知道广播方的口号,然后绑定此端口号才能正确接收。
2. 接收方的Socket不需要设置成广播属性。
3. 绑定的IP不可以使用“127.0.0.1”,可以使用真实IP地址或者INADDR_ANY。否则接收失败。
客户端:
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define false -1
int main()
{
setvbuf(stdout, NULL, _IONBF, 0);
fflush(stdout);
// 绑定地址
struct sockaddr_in addrto;
bzero(&addrto, sizeof(struct sockaddr_in));
addrto.sin_family = AF_INET;
addrto.sin_addr.s_addr = htonl(INADDR_ANY);
addrto.sin_port = htons(8000);
// 广播地址
struct sockaddr_in from;
bzero(&from, sizeof(struct sockaddr_in));
from.sin_family = AF_INET;
from.sin_addr.s_addr = htonl(INADDR_ANY);
from.sin_port = htons(8000);
int sock = -1;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
printf("socket error\n");
return false;
}
const int opt = 1;
//设置该套接字为广播类型,
if(bind(sock,(struct sockaddr *)&(addrto), sizeof(struct sockaddr_in)) == -1)
{
printf("bind error\n");
return false;
}
int len = sizeof(struct sockaddr_in);
char smsg[100] = {0};
while(1)
{
//从广播地址接受消息
int ret=recvfrom(sock, smsg, 100, 0, (struct sockaddr*)&from,(socklen_t*)&len);
if(ret<=0)
{
printf("read error\n");
}
else
{
printf("%s\t", smsg);
}
sleep(1);
}
return 0;
}
服务器端:
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define false -1
int main()
{
setvbuf(stdout, NULL, _IONBF, 0); //把缓冲区与流相关
fflush(stdout);
int sock = -1;
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
printf("socket error\n");
return false;
}
const int opt = 1;
//设置该套接字为广播类型,
int nb = 0;
nb = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));
if(nb == -1)
{
printf("set socket error\n");
return false;
}
struct sockaddr_in addrto;
bzero(&addrto, sizeof(struct sockaddr_in));
addrto.sin_family=AF_INET;
addrto.sin_addr.s_addr = inet_addr("192.168.1.255");
addrto.sin_port=htons(8000);
int nlen=sizeof(addrto);
while(1)
{
sleep(1);
//从广播地址发送消息
char smsg[] = {"abcdef"};
int ret=sendto(sock, smsg, strlen(smsg), 0, (struct sockaddr*)&addrto, nlen);
if(ret<0)
{
printf("send error\n");
}
else
{
printf("ok \n");
}
}
return 0;
}