首页 > 代码库 > UDP组播相关

UDP组播相关

Windows服务端

#include "stdafx.h"


#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <stdio.h> 
#include <stdlib.h> 
#define MCASTADDR "239.255.255.239" //本例使用的多播组地址。 
#define MCASTPORT 9111 //绑定的本地端口号。 
#define BUFSIZE 1024 //接收数据缓冲大小。
#pragma comment(lib,"Ws2_32.lib.")

int main( int argc,char ** argv) 
{
	WSADATA wsd; 

	struct sockaddr_in local,remote,from; 
	SOCKET sock,sockM; 
	char recvbuf[BUFSIZE]; 
	int len = sizeof( struct sockaddr_in); 
	int ret; //初始化WinSock2.2 
	if( WSAStartup( MAKEWORD(2,2),&wsd) != 0 ) 
	{ 
		printf("WSAStartup() failed\n"); return -1; 
	} 
    if((sock=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0, WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_MULTIPOINT_D_LEAF| WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
	{ 
		printf("socket failed with:%d\n",WSAGetLastError());
	    WSACleanup(); 
		return -1; 
	} 
	//将sock绑定到本机某端口上。 
	local.sin_family = AF_INET; 
	local.sin_port = htons(MCASTPORT); 
	local.sin_addr.s_addr = INADDR_ANY; 
	if( bind(sock,(struct sockaddr*)&local,sizeof(local)) == SOCKET_ERROR ) 
	{
		printf( "bind failed with:%d \n",WSAGetLastError()); 
		closesocket(sock); 
		WSACleanup();
		return -1; 
	} //加入多播组 
	remote.sin_family = AF_INET; 
	remote.sin_port = htons(MCASTPORT); 
	remote.sin_addr.s_addr = inet_addr( MCASTADDR ); 
	if(( sockM = WSAJoinLeaf(sock,(SOCKADDR*)&remote,sizeof(remote), NULL,NULL,NULL,NULL, JL_BOTH)) == INVALID_SOCKET) 
	{ 
		printf("WSAJoinLeaf() failed:%d\n",WSAGetLastError()); 
		closesocket(sock);
		WSACleanup();
		return -1; 
	} //接收多播数据,当接收到的数据为"QUIT"时退出。 
	while(1) 
	{ 
		if(( ret = recvfrom(sock,recvbuf,BUFSIZE,0, (struct sockaddr*)&from,&len)) == SOCKET_ERROR) 
		{ 
			printf("recvfrom failed with:%d\n",WSAGetLastError()); 
			closesocket(sockM); 
			closesocket(sock); 
			WSACleanup(); 
			return -1; 
		} if( strcmp(recvbuf,"QUIT") == 0 )
			break; 
		else { 
			recvbuf[ret] = ‘\0‘; 
			printf("RECV:‘ %s ‘ FROM <%s> \n",recvbuf,inet_ntoa(from.sin_addr));
		} 
	} 
	closesocket(sockM); 
	closesocket(sock); 
	WSACleanup(); 
	return 0; 
}

  

windows客户端

#include "stdafx.h"


#include <stdio.h>  
#include <winsock2.h>  
#include <ws2tcpip.h>  
#pragma comment(lib, "ws2_32.lib")  

int main()  
{  
	WSADATA wsaData;  
	WSAStartup(MAKEWORD(2, 2), &wsaData);     

	SOCKET sock = socket(AF_INET,SOCK_DGRAM,0);  

	sockaddr_in my;  
	my.sin_family = AF_INET;  
	//my.sin_addr.S_un.S_addr = inet_addr("192.168.199.133"); 
	my.sin_addr.S_un.S_addr=INADDR_ANY;
	my.sin_port = htons(56789);  

	bind(sock, (sockaddr*)&my, sizeof(my));



	int n = 1; // 注意, 这个n值很重要, 下面我会讲到  
	setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&n, sizeof(n));  

	sockaddr_in addr;  
	addr.sin_addr.S_un.S_addr = inet_addr("239.255.255.239");  
	addr.sin_family = AF_INET;  
	addr.sin_port = htons(9111);  

	static int i = 0;  
	while(1)  
	{     
		char buf[100] = {0};  
		sprintf_s(buf, "blablablabla:%d", i++);  
		sendto(sock, buf, strlen(buf) + 1, 0, (sockaddr*)&addr, sizeof(sockaddr));  
		Sleep(500);   
	}  

	closesocket(sock);  
	WSACleanup();  

	return 0;  
}  

  

Linux服务端

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>

#define BUFLEN 255
/*********************************************************************
*filename: mcastserver.c
*purpose: 演示组播编程的基本步骤,组播服务器端,关键在于加入组
*tidied by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-01-25 13:20:00
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to: Google.com
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char **argv)
{
struct sockaddr_in peeraddr;
struct in_addr ia;
int sockfd;
char recmsg[BUFLEN + 1];
unsigned int socklen, n;
struct hostent *group;
struct ip_mreq mreq;

/* 创建 socket 用于UDP通讯 */
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
printf("socket creating err in udptalk\n");
exit(1);
}

/* 设置要加入组播的地址 */
bzero(&mreq, sizeof(struct ip_mreq));
if (argv[1]) {
    if ((group = gethostbyname(argv[1])) == (struct hostent *) 0) {
        perror("gethostbyname");
        exit(errno);
    }
} else {
    printf
        ("you should give me a group address, 224.0.0.0-239.255.255.255\n");
    exit(errno);
}

bcopy((void *) group->h_addr, (void *) &ia, group->h_length);
/* 设置组地址 */
bcopy(&ia, &mreq.imr_multiaddr.s_addr, sizeof(struct in_addr));

/* 设置发送组播消息的源主机的地址信息 */
mreq.imr_interface.s_addr = htonl(INADDR_ANY);

/* 把本机加入组播地址,即本机网卡作为组播成员,只有加入组才能收到组播消息 */
if (setsockopt
        (sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
         sizeof(struct ip_mreq)) == -1) {
    perror("setsockopt");
    exit(-1);
}

socklen = sizeof(struct sockaddr_in);
memset(&peeraddr, 0, socklen);
peeraddr.sin_family = AF_INET;
if (argv[2])
    peeraddr.sin_port = htons(atoi(argv[2]));
    else
    peeraddr.sin_port = htons(7838);
    if (argv[1]) {
        if (inet_pton(AF_INET, argv[1], &peeraddr.sin_addr) <= 0) {
            printf("Wrong dest IP address!\n");
            exit(0);
        }
    } else {
        printf("no group address given, 224.0.0.0-239.255.255.255\n");
        exit(errno);
    }

/* 绑定自己的端口和IP信息到socket上 */
if (bind
        (sockfd, (struct sockaddr *) &peeraddr,
         sizeof(struct sockaddr_in)) == -1) {
    printf("Bind error\n");
    exit(0);
}

/* 循环接收网络上来的组播消息 */
for (;;) {
    bzero(recmsg, BUFLEN + 1);
    n = recvfrom(sockfd, recmsg, BUFLEN, 0,
            (struct sockaddr *) &peeraddr, &socklen);
    if (n < 0) {
        printf("recvfrom err in udptalk!\n");
        exit(4);
    } else {
        /* 成功接收到数据报 */
        recmsg[n] = 0;
        printf("peer:%s", recmsg);
    }
}
}

  Linux客户端

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFLEN 255
/*********************************************************************
 *filename: mcastclient.c
 *purpose: 演示组播编程的基本步骤,其实这就是一个基本的UDP客户端程序
 *tidied by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
 Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
 *date time:2007-01-25 13:10:00
 *Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
 * 但请遵循GPL
 *Thanks to: Google.com
 *Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
 * 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
 *********************************************************************/
int main(int argc, char **argv)
{
    struct sockaddr_in peeraddr, myaddr;

    int sockfd;
    char recmsg[BUFLEN + 1];
    unsigned int socklen;

    /* 创建 socket 用于UDP通讯 */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0) {
        printf("socket creating error\n");
        exit(1);
    }
    socklen = sizeof(struct sockaddr_in);

    /* 设置对方的端口和IP信息 */
    memset(&peeraddr, 0, socklen);
    peeraddr.sin_family = AF_INET;
    if (argv[2])
        peeraddr.sin_port = htons(atoi(argv[2]));
    else
        peeraddr.sin_port = htons(7838);
    if (argv[1]) {
        /* 注意这里设置的对方地址是指组播地址,而不是对方的实际IP地址 */
        if (inet_pton(AF_INET, argv[1], &peeraddr.sin_addr) <= 0) {
            printf("wrong group address!\n");
            exit(0);
        }
    } else {
        printf("no group address!\n");
        exit(0);
    }

    /* 设置自己的端口和IP信息 */
    memset(&myaddr, 0, socklen);
    myaddr.sin_family = AF_INET;
    if (argv[4])
        myaddr.sin_port = htons(atoi(argv[4]));
    else
        myaddr.sin_port = htons(23456);

    if (argv[3]) {
        if (inet_pton(AF_INET, argv[3], &myaddr.sin_addr) <= 0) {
            printf("self ip address error!\n");
            exit(0);
        }
    } else
        myaddr.sin_addr.s_addr = INADDR_ANY;

    /* 绑定自己的端口和IP信息到socket上 */
    if (bind
            (sockfd, (struct sockaddr *) &myaddr,
             sizeof(struct sockaddr_in)) == -1) {
        printf("Bind error\n");
        exit(0);
    }

    /* 循环接受用户输入的消息发送组播消息 */
    for (;;) {
        /* 接受用户输入 */
        bzero(recmsg, BUFLEN + 1);
        if (fgets(recmsg, BUFLEN, stdin) == (char *) EOF)
            exit(0);
        /* 发送消息 */
        if (sendto
                (sockfd, recmsg, strlen(recmsg), 0,
                 (struct sockaddr *) &peeraddr,
                 sizeof(struct sockaddr_in)) < 0) {
            printf("sendto error!\n");
            exit(3);
        }
        printf("‘%s‘ send ok\n", recmsg);
    }
}

  windows收发可用,linux发可用,收每隔一段时间收到一堆包,不能实时接收,可能是防火墙之类的问题。

UDP组播相关