Windows系统下的组播发送
//==============send.h==================
#ifndef SEND_H_
#define SEND_H_
#include <string>
#include <WinSock.h> //windows 网络的函数所在的头文件
using namespace std;
class Send
{
public:
Send(void);
public:
~Send(void);
public:
/* 对连接进行初始化 strIPAddress:广播的ip地址 strPort: 端口号*/
bool InitSocket(const string strIPAddress,const string strPort);
void CleanSocket(); //清理socket
bool SendStringData(const string strMessage); //发送字符串数据
bool SendStructeData(const Person person); //发送指定结构体数据(已Person为例)
private:
void InitSockAddress(const string strIPAddress,const string strPort);
private:
SOCKET m_socket; //socket
sockaddr_in m_sockLocalAddress; //本地sock地址
sockaddr_in m_sockDesAddress; //目的sock地址
};
#endif //SEND_H_
//========Send.cpp================
#include <iostream>
#include "Send.h"
using namespace std;
Send::Send(void)
{
m_socket = INVALID_SOCKET;
WSAData ws;
//每个Winsock程序必须使用WSAStartup载入合适的Winsock动态链接库
if (WSAStartup(MAKEWORD(1,1),&ws)!=0)
{
cout<<"WSAStartup failed! Error: "<<WSAGetLastError()<<endl;
}
}
Send::~Send(void)
{
WSACleanup();
}
bool Send::InitSocket(const string strIPAddress,const string strPort)
{
//创建套接字,ipv4,报文,udp协议
m_socket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
//创建socket失败
if (INVALID_SOCKET == m_socket)
{
cout<<"failed to create socket"<<endl;
return false;
}
//初始化sock地址
InitSockAddress(strIPAddress,strPort);
// 绑定
if (bind (m_socket,
(struct sockaddr FAR *) &m_sockLocalAddress,
sizeof (m_sockLocalAddress)) == SOCKET_ERROR)
{
//报错
cout<<"Binding socket failed! Error: "<<WSAGetLastError()<<endl;
closesocket (m_socket);
return false;
}
int iOptVal=64; //1秒
// 设置组播存活时间
if (setsockopt (m_socket,IPPROTO_IP,3,(char FAR *)&iOptVal,sizeof (int)) == SOCKET_ERROR)
{
//报错
cout<<"setsockopt failed! Error:"<<WSAGetLastError()<<endl;
closesocket (m_socket);
return false;
}
return true;
}
void Send::CleanSocket()
{
shutdown(m_socket,0x01);
closesocket(m_socket);
}
bool Send::SendStringData(const string strMessage)
{
if (sendto (m_socket,
(char *)&strMessage,
sizeof(strMessage),
0,
(struct sockaddr FAR *) &m_sockDesAddress,
sizeof (m_sockDesAddress)) == SOCKET_ERROR)
{
//报错
cout<<"sendto failed! Error: %d"<<WSAGetLastError ()<<endl;
closesocket (m_socket);
return false;
}
else
return true;
}
bool Send::SendStructeData(const Person person)
{
if (sendto (m_socket,(char *)&person,sizeof(person),0,(struct sockaddr FAR *) &m_sockDesAddress,sizeof (m_sockDesAddress)) == SOCKET_ERROR)
{
//报错
cout<<"sendto failed! Error: %d"<<WSAGetLastError ()<<endl;
closesocket (m_socket);
return false;
}
else
return true;
}
void Send::InitSockAddress(const string strIPAddress,const string strPort)
{
//本地sock地址设置
m_sockLocalAddress.sin_family = AF_INET; //ipv4地址类型
m_sockLocalAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
m_sockLocalAddress.sin_port = htons(0);
memset(m_sockLocalAddress.sin_zero,0,8);
//目的sock地址设置
m_sockDesAddress.sin_family = AF_INET; //IPv4版本
m_sockDesAddress.sin_port = htons (atol(strPort.c_str())); //端口
m_sockDesAddress.sin_addr.s_addr = inet_addr (strIPAddress.c_str()); //地址
}
Windows之组播接收
//==================receive.h===================
#ifndef RECEIVE_H_
#define RECEIVE_H_
#include <string>
#include <WinSock.h>
using namespace std;
class Receive
{
public:
Receive(void);
public:
~Receive(void);
public:
//初始化socket
bool InitSocket(const string strIPAddress,const string strPort);
//接受string数据
bool ReceiveStringData(string& strMessage);
//接受结构体数据
bool ReceiveStructeData();
//关闭socket
void CloseSocket();
private:
SOCKET m_socket; //socket;
sockaddr_in m_sockLocalAddress;
sockaddr_in m_sockReceiveAddress;
};
#endif //RECEIVE_H_
//===================receive.cpp================
#include <iostream>
#include "Receive.h"
using namespace std;
Receive::Receive(void)
{
m_socket =INVALID_SOCKET;
//初始化winsock
WSAData ws;
if (WSAStartup(MAKEWORD(1,1),&ws))
{
cout<<"WSAStartup failed"<<WSAGetLastError()<<endl;
}
}
Receive::~Receive(void)
{
WSACleanup();
}
bool Receive::InitSocket(const string strIPAddress,const string strPort)
{
struct ip_mreq mreq; // 用于表示组播组地址的结构
// 创建数据报类型的socket
if ((m_socket = socket (AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
//报错
cout<<"Allocating socket failed! Error:"<<WSAGetLastError()<<endl;
return FALSE;
}
// 设定本地Socket地址信息
m_sockLocalAddress.sin_family = AF_INET;//IPv4版本
m_sockLocalAddress.sin_port = htons (atol(strPort.c_str())); //端口
m_sockLocalAddress.sin_addr.s_addr = htonl (INADDR_ANY); //地址
// 绑定
if (bind (m_socket,
(struct sockaddr FAR *) &m_sockLocalAddress,
sizeof (m_sockLocalAddress)) == SOCKET_ERROR)
{
//报错
cout<<"Binding socket failed! Error: "<<WSAGetLastError()<<endl;
closesocket (m_socket);
return FALSE;
}
//组播地址
mreq.imr_multiaddr.s_addr = inet_addr (strIPAddress.c_str());
//透明所有协议
mreq.imr_interface.s_addr = INADDR_ANY;
//设置套接字选项,加入一个多播组
if (setsockopt (m_socket,
IPPROTO_IP,
IP_ADD_MEMBERSHIP,
(char FAR *)&mreq,
sizeof (mreq)) == SOCKET_ERROR)
{
//报错
cout<<"setsockopt failed! Error: "<<WSAGetLastError()<<endl;
closesocket (m_socket);
return FALSE;
}
return true;
}
bool Receive::ReceiveStringData(string& strMessage)
{
m_sockReceiveAddress.sin_family = AF_INET;
int iRecvLen = sizeof(m_sockReceiveAddress);
// 从组播组接收数据报
if (recvfrom (m_socket,
//接收数据的缓冲区
(char *)&strMessage,
//缓冲区长度
100,
//接收数据的方式
0,
(struct sockaddr FAR *)&m_sockReceiveAddress,
&iRecvLen) == SOCKET_ERROR)
{
//报错
cout<<"recvfrom failed! Error: "<<WSAGetLastError()<<endl;
closesocket (m_socket);
return FALSE;
}
else
{
return true;
}
}
void Receive::CloseSocket()
{
// 禁用套接字
shutdown (m_socket, 0x00);
// 关闭套接字
closesocket (m_socket);
}
Windows 下的 main.c
#include <iostream>
#include "Send.h"
#include "Receive.h"
using namespace std;
int main()
{
Send send;
Receive receive;
send.InitSocket("224.0.1.2","7838");
receive.InitSocket("224.0.1.2","7838");
if(1){
while(1)
{
if (send.SendStringData("dddd"))
{
cout<<"send success"<<endl;
}
}
send.CleanSocket();
}else{
while (1)
{
receive.ReceiveStringData(strMessage);
cout<<strMessage<<endl;
}
receive.CloseSocket();
}
}
QT之组播通信
/*(Multicast)在发送者和每一接收者之间实现点对多点网络连接。\
如果一台发送者同时给多个的接收者传输相同的数据,也只需复制一份的相同数据包。\
它提高了数据传送效率。减少了骨干网络出现拥塞的可能性。*/
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::Any, 9999, QUdpSocket::ShareAddress);
udpSocket->joinMulticastGroup(QHostAddress("224.0.0.2"));
//=========receive============
QHostAddress ip;
quint16 port;
udpSocket->readDatagram(buf,sizeof(buf),&ip,&port);
//=========receive============
QString str = "zzczzczzczzczzczzczzc!";
clientsocket->writeDatagram(str.toUtf8(),QHostAddress("224.0.0.2"),9999);
Linux之组播通信 服务端
//========================Linux 组播实现========================
//linux中对struct ip_mreqn 结构体的定义
struct ip_mreqn {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_address; /* local IP address of interface */
int imr_ifindex; /* Interface index */
};
//----server.c------
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h>
#define SERVER_PORT 8000
#define CLIENT_PORT 9000
#define MAXLINE 1500
#define GROUP "239.0.0.2"
//239.0.0.0~239.255.255.255
int main(void)
{
int sockfd;
struct sockaddr_in serveraddr, clientaddr;
char buf[MAXLINE] = "multicast\n";
struct ip_mreqn group;
sockfd = socket(AF_INET, SOCK_DGRAM, 0); /*构造用于UDP通信的套接字*/
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET; /* IPv4 */
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); /*本地任意IP INADDR_ANY = 0 */
serveraddr.sin_port = htons(SERVER_PORT);
bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
inet_pton(AF_INET, GROUP, &group.imr_multiaddr); /*设置组播组的地址*/
inet_pton(AF_INET, "0.0.0.0", &group.imr_address); /* 本地任意IP 自动分配有效IP*/
group.imr_ifindex = if_nametoindex("eth0"); /* 给出网卡名,转换为对应编号:eth0 --> 编号 ,, 命令:ip ad */
setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &group, sizeof(group)); /*获取组播权限*/
bzero(&clientaddr, sizeof(clientaddr)); /* 构造client 地址 IP+端口号*/
clientaddr.sin_family = AF_INET;
inet_pton(AF_INET, GROUP, &clientaddr.sin_addr.s_addr); /* IPv4 239.0.0.2+9000 */
clientaddr.sin_port = htons(CLIENT_PORT);
int i = 0;
while (1) {
sprintf(buf, "multicast %d\n", i++);
//fgets(buf, sizeof(buf), stdin);
sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&clientaddr, sizeof(clientaddr));
sleep(1);
}
close(sockfd);
return 0;
}
Linux之组播通信 客户端
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <net/if.h>
#define SERVER_PORT 8000
#define CLIENT_PORT 9000
#define GROUP "239.0.0.2"
int main(int argc, char *argv[])
{
struct sockaddr_in localaddr;
int confd;
ssize_t len;
char buf[BUFSIZ];
struct ip_mreqn group; /*组播结构体*/
confd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&localaddr, sizeof(localaddr)); /* 初始化*/
localaddr.sin_family = AF_INET;
inet_pton(AF_INET, "0.0.0.0" , &localaddr.sin_addr.s_addr);
localaddr.sin_port = htons(CLIENT_PORT);
bind(confd, (struct sockaddr *)&localaddr, sizeof(localaddr));
inet_pton(AF_INET, GROUP, &group.imr_multiaddr); /* 设置组播组地址*/
inet_pton(AF_INET, "0.0.0.0", &group.imr_address); /*使用本地任意IP添加到组播组*/
group.imr_ifindex = if_nametoindex("eth0"); /* 设置网卡名 编号 ip ad */
setsockopt(confd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group));/* 将client加入组播组*/
while (1) {
len = recvfrom(confd, buf, sizeof(buf), 0, NULL, 0);
write(STDOUT_FILENO, buf, len);
}
close(confd);
return 0;
}