转自 《 荡胸生层云:C语言开发修行实录》。席国庆等编著。
功能描述:
本项目既有广播的功能,又有多播的功能,能实现基本的广播和多播机制,其主要包括如下功能。
代码如下:
//preprocessing.h
#pragma comment(lib,"ws2_32.lib")
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
#define MCASTADDR "210.31.110.37"
#define MCASTPORT 25000
#define BUFSIZE 1024
#define BCOUNT 10
#define BCASTPORT 5050
#define MCOUNT 10
SOCKET socketBro;
SOCKET socketRec;
struct sockaddr_in addrBro;
struct sockaddr_in addrRec;
BOOL broadSendFlag;
BOOL broadFlag;
DWORD bCount;
DWORD bcastAddr;
short bPort;
SOCKET socketMul;
SOCKET sockJoin;
struct sockaddr_in addrLocal;
struct sockaddr_in addrMul;
BOOL multiSendFlag;
BOOL bLoopBack;
BOOL multiFlag;
DWORD dwInterface;
DWORD dwMulticastGroup;
DWORD mCount;
short mPort;
void initial();
void GetArgments(int argc,char **argv);
void userHelpAll();
void userHelpBro();
void userHelpMul();
void broadcastSend();
void broadcastRec();
void mulControl();
void multicastSend();
void multicastRec();
//function.c
#include "preprocessing.h"
void initial()
{
bPort=BCASTPORT;
bCount=BCOUNT;
bcastAddr=INADDR_BROADCAST;
broadSendFlag=FALSE;
broadFlag=FALSE;
multiFlag=FALSE;
dwInterface=INADDR_ANY;
dwMulticastGroup=inet_addr(MCASTADDR);
mPort=MCASTPORT;
mCount=MCOUNT;
multiSendFlag=FALSE;
bLoopBack=FALSE;
}
void GetArgments(int argc,char **argv)
{
int i;
if (argc<=1)
{
userHelpAll();
return;
}
if (argv[1][0]=='-'&&argv[1][1]=='b')
{
broadFlag=TRUE;
for (i=0;i<argc;i++)
{
if (argv[i][0]=='-')
{
switch(tolower(argv[i][1]))
{
case 's':
broadSendFlag=TRUE;
break;
case 'h':
if (strlen(argv[i])>3)
bcastAddr=inet_addr(&argv[i][3]);
break;
case 'p':
if (strlen(argv[i])>3)
bPort=atoi(&argv[i][3]);
break;
case 'n':
bCount=atoi(&argv[i][3]);
break;
default :
{
userHelpBro();
ExitProcess(-1);
}
break;
}
}
}
return;
}
if (argv[1][0]=='-'&&argv[1][1]=='m')
{
multiFlag=TRUE;
for (i=2;i<argc;i++)
{
if (argv[i][0]=='-')
{
switch(tolower(argv[i][1]))
{
case 's':
multiSendFlag=TRUE;
break;
case 'h':
if (strlen(argv[i])>3)
dwMulticastGroup=inet_addr(&argv[i][3]);
break;
case 'i':
if (strlen(argv[i])>3)
dwInterface=inet_addr(&argv[i][3]);
break;
case 'p':
if (strlen(argv[i])>3)
mPort=atoi(&argv[i][3]);
break;
case 'l':
bLoopBack=TRUE;
break;
case 'n':
mCount=atoi(&argv[i][3]);
break;
default :
userHelpMul();
break;
}
}
}
}
return;
}
void userHelpAll()
{
printf("please choose broadcast[-b] or multicast[-m]!\n");
printf("userHelpAll: -b [-s] [p][-h][-n] | -m[-s][-h][-p][-i][-l][-n]\n");
userHelpBro();
userHelpMul();
}
void userHelpBro()
{
printf("Broadcast:-b -s:str -p:int -h:str -n:int\n");
printf("-b start the broadcast program\n");
printf("-s act as server(send data);otherwise receive data.default is receiver\n");
printf("-h str the decimal broadcast ip address to join\n the default group is %s\n",MCASTADDR);
printf("-n:int the number of messages to send/receive.\n");
printf("the default number is 10\n");
}
void userHelpMul()
{
printf("Multicast: -m -s -h:str -p:int -i:str -l -n:int\n");
printf("-m start the multicast program.\n");
printf("-s act as server(send data);otherwise receive data.default is receiver\n");
printf("-h str the decimal broadcast ip address to join\n the default group is %s\n",MCASTADDR);
ExitProcess(-1);
}
void broadcastSend()
{
char *smsg="hello Mr shu\n";
BOOL opt=TRUE;
int nlen=sizeof(addrBro);
int ret;
DWORD i=0;
socketBro=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
if (socketBro==INVALID_SOCKET)
{
printf("create socket failed:%d\n",WSAGetLastError());
WSACleanup();
return;
}
addrBro.sin_family=AF_INET;
addrBro.sin_addr.s_addr=bcastAddr;
addrBro.sin_port=htons(bPort);
if (setsockopt(socketBro,SOL_SOCKET,SO_BROADCAST,(char FAR *)&opt,sizeof(opt))==SOCKET_ERROR)
{
printf("setsockopt failed:%d",WSAGetLastError());
closesocket(socketBro);
WSACleanup();
return;
}
while (i<bCount)
{
Sleep(1000);
ret=sendto(socketBro,smsg,256,0,(struct sockaddr*)&addrBro,nlen);
if (ret==SOCKET_ERROR)
{
printf("sEND FAILED:%d",WSAGetLastError());
}
else
{
printf("send message %d\n",i);
}
i++;
}
closesocket(socketBro);
WSACleanup();
}
void broadcastRec()
{
BOOL optval=TRUE;
int addrBroLen;
char buf[256];
DWORD i=0;
addrRec.sin_family=AF_INET;
addrRec.sin_addr.s_addr=0;
addrRec.sin_port=htons(bPort);
addrBro.sin_family=AF_INET;
addrBro.sin_addr.s_addr=bcastAddr;
addrBro.sin_port=htons(bPort);
addrBroLen=sizeof(addrBro);
socketRec=socket(AF_INET,SOCK_DGRAM,0);
if(socketRec==INVALID_SOCKET)
{
printf("CREATE SOCKET ERROR:%d",WSAGetLastError());
WSACleanup();
return;
}
if(setsockopt(socketRec,SOL_SOCKET,SO_REUSEADDR,(char FAR *)&optval,sizeof(optval))==SOCKET_ERROR)
{
printf("setsockopt failed:%d",WSAGetLastError());
closesocket(socketRec);
WSACleanup();
return;
}
if (bind(socketRec,(struct sockaddr *)&addrRec,sizeof(struct sockaddr_in))==SOCKET_ERROR)
{
printf("bind failed with :%d\n",WSAGetLastError());
closesocket(socketRec);
WSACleanup();
return;
}
while(i<bCount)
{
recvfrom(socketRec,buf,256,0,(struct sockaddr FAR *)&addrBro,(int FAR *)&addrBroLen);
Sleep(2000);
printf("%s\n",buf);
ZeroMemory(buf,256);
i++;
}
closesocket(socketRec);
WSACleanup();
}
void mulControl()
{
int optval;
if ((socketMul=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_MULTIPOINT_D_LEAF|WSA_FLAG_MULTIPOINT_C_LEAF|WSA_FLAG_OVERLAPPED))==INVALID_SOCKET)
{
printf("SOCKET FAILED WITH:%d\n",WSAGetLastError());
WSACleanup();
return;
}
addrLocal.sin_family=AF_INET;
addrLocal.sin_port=htons(mPort);
addrLocal.sin_addr.s_addr=dwInterface;
if (bind(socketMul,(struct sockaddr *)&addrLocal,sizeof(addrLocal))==SOCKET_ERROR)
{
printf("bind failed with:%d\n",WSAGetLastError());
closesocket(socketMul);
WSACleanup();
return;
}
addrMul.sin_family=AF_INET;
addrMul.sin_port=htons(mPort);
addrMul.sin_addr.s_addr=dwMulticastGroup;
optval=8;
if (setsockopt(socketMul,IPPROTO_IP,IP_MULTICAST_TTL,(char *)&optval,sizeof(int))==SOCKET_ERROR)
{
printf("setsockopt(IP_MULTICAST_TTL)failed:%d\n",WSAGetLastError());
closesocket(socketMul);
WSACleanup();
return;
}
if (bLoopBack)
{
optval=0;
if (setsockopt(socketMul,IPPROTO_IP,IP_MULTICAST_LOOP,(char *)&optval,sizeof(optval))==SOCKET_ERROR)
{
printf("setsockopt(IP_MULTICAST_LOOP)failed:%d\n",WSAGetLastError());
closesocket(socketMul);
WSACleanup();
return;
}
}
if ((sockJoin=WSAJoinLeaf(socketMul,(SOCKADDR *)&addrMul,sizeof(addrMul),NULL,NULL,NULL,NULL,JL_BOTH))==INVALID_SOCKET)
{
printf("WSAJoinLeaf() failed:%d\n",WSAGetLastError());
closesocket(socketMul);
WSACleanup();
return;
}
}
void multicastSend()
{
TCHAR sendbuf[BUFSIZE];
DWORD i;
int ret;
mulControl();
for (i=0;i<mCount;i++)
{
sprintf(sendbuf,"server 1:this is a test:%d",i);
ret=sendto(socketMul,(char *)sendbuf,strlen(sendbuf),0,(struct sockaddr *)&addrMul,sizeof(addrMul));
if (ret==SOCKET_ERROR)
{
printf("sent to failed with:%d\n",WSAGetLastError());
closesocket(sockJoin);
closesocket(socketMul);
WSACleanup();
return;
}
else
{
printf("send message %d\n",i);
Sleep(500);
}
closesocket(socketMul);
WSACleanup();
}
}
void multicastRec()
{
DWORD i;
struct sockaddr_in from;
TCHAR recvbuf[BUFSIZE];
int ret;
int len=sizeof(struct sockaddr_in);
mulControl();
for (i=0;i<mCount;i++)
{
if ((ret=recvfrom(socketMul,recvbuf,BUFSIZE,0,(struct sockaddr *)&from,&len))==SOCKET_ERROR)
{
printf("recvfrom failed with:%d\n",WSAGetLastError());
closesocket(sockJoin);
closesocket(socketMul);
WSACleanup();
return;
}
recvbuf[ret]=0;
printf("recv:'%s' from <%s>\n",recvbuf,inet_ntoa(from.sin_addr));
}
closesocket(socketMul);
WSACleanup();
}
//main.c
#include <stdio.h>
#include "preprocessing.h"
int main(int argc,char ** argv)
{
int i;
printf("%d\n",argc);
for (i=0;i<argc;i++)
{
if (strlen(argv[i])>3)
{
printf("%c\n",argv[i][3]);
}
//printf("%s\n",argv[i]);
//printf("%s\n",argv[i]);
//printf("%s\n",argv[i]);
}
scanf("&i");
/*WSADATA wsd;
initial();
GetArgments(argc,argv);
if (WSAStartup(MAKEWORD(2,2),&wsd)!=0)
{
printf("WSAStartup() failed\n");
return -1;
}
if (broadFlag)
{
if (broadSendFlag)
{
broadcastSend();
return 0;
}
else
{
broadcastRec();
return 0;
}
}
if (multiFlag)
{
if (multiSendFlag)
{
multicastSend();
return 0;
}
else
{
multicastRec();
return 0;
}
}
return 0;*/
}
共三个文件。