📄 mcastatm.cpp
字号:
// Module: mcastatm.cpp
//
// Description:
// This sample illustrates multicasting on an ATM network.
// ATM multicasting features rooted control and data planes.
// This means our multicast server explicitly invites each
// leaf not via a WSAJoinLeaf call. The leaf nodes simply
// wait for on an accept for the invitation.
//
// For the root node we specify the -s options along with
// one or more -l:Address options. The address is the ATM
// address of the leaf to invite. All ATM addresses are only
// the first 38 chars. The port (selector) which is the other
// 2 characters of the address are given in the -p:xx option.
//
// For the client simply call the app with no paramters (the
// -i:Addr can be used for both client and server).
//
// Compilation:
// cl -o mcastatm.exe mcastatm.cpp suport.cpp ws2_32.lib
//
// Command Line Options/Parametrs:
// mcastatm.exe -s -l ATM-Addr -i ATM-Addr -p XX -n int
// -s Act as root\n");
// -l str Leaf address to invite (38 chars)
// May be specified multiple times.
// -i str Local interface to bind to (38 chars)
// -p xx Port number (2 hex chars)
// -n int Number of packets to send
//
#include "support.h"
#include <stdio.h>
#include <stdlib.h>
#define BUFSIZE 1024
#define MAX_ATM_LEAF 4
#define ATM_PORT_OFFSET ((ATM_ADDR_SIZE*2)-2)
#define MAX_ATM_STR_LEN (ATM_ADDR_SIZE*2)
DWORD dwAddrCount=0,
dwDataCount=20;
BOOL bServer=FALSE,
bLocalAddress=FALSE;
char szLeafAddresses[MAX_ATM_LEAF][MAX_ATM_STR_LEN+1],
szLocalAddress[MAX_ATM_STR_LEN+1],
szPort[3];
SOCKET sLeafSock[MAX_ATM_LEAF];
// Module: usage
//
// Description:
// Print usage information.
//
void usage(char *progname)
{
printf("usage: %s [-s]\n", progname);
printf(" -s Act as root\n");
printf(" -l str Leaf address to invite (38 chars)\n");
printf(" May be specified multiple times\n");
printf(" -i str Local interface to bind to (38 chars)\n");
printf(" -p xx Port number (2 hex chars)\n");
printf(" -n int Number of packets to send\n");
ExitProcess(1);
}
// Module: ValidateArgs
//
// Description:
// Parse command line arguments.
//
void ValidateArgs(int argc, char **argv)
{
int i;
memset(szLeafAddresses, 0, MAX_ATM_LEAF * (MAX_ATM_STR_LEN+1));
memset(szPort, 0, sizeof(szPort));
for(i=1; i < argc ;i++)
{
if ((argv[i][0] == '-') || (argv[i][0] == '/'))
{
switch (tolower(argv[i][1]))
{
case 's': // server
bServer = TRUE;
break;
case 'l': // leaf address
if (i+1 >=argc)
usage(argv[0]);
strncpy(szLeafAddresses[dwAddrCount++], argv[++i], MAX_ATM_STR_LEN-2);
break;
case 'i': // local interface
if (i+1 >= argc)
usage(argv[0]);
strncpy(szLocalAddress, argv[++i], MAX_ATM_STR_LEN-2);
bLocalAddress = TRUE;
break;
case 'p': // port address to use
if (i+1 >= argc)
usage(argv[0]);
strncpy(szPort, argv[++i], 2);
break;
case 'n': // number of packets to send
if (i+1 >= argc)
usage(argv[0]);
dwDataCount = atoi(argv[++i]);
break;
default:
usage(argv[0]);
break;
}
}
}
return;
}
//
// Function: Server
//
// Description:
// Bind to the local interface and then invite each leaf
// address which was specified on the command line.
// Once each connection is made, send some data.
//
void Server(SOCKET s, WSAPROTOCOL_INFO *lpSocketProtocol)
{
// Server routine
//
SOCKADDR_ATM atmleaf, atmroot;
WSABUF wsasend;
char sendbuf[BUFSIZE],
szAddr[BUFSIZE];
DWORD dwBytesSent,
dwAddrLen=BUFSIZE,
dwNumInterfaces,
i;
int ret;
// If no specified local interface is given pick the first
// one
//
memset(&atmroot, 0, sizeof(SOCKADDR_ATM));
if (!bLocalAddress)
{
dwNumInterfaces = GetNumATMInterfaces(s);
GetATMAddress(s, 0, &atmroot.satm_number);
}
else
AtoH((char *)&atmroot.satm_number.Addr[0], szLocalAddress,
ATM_ADDR_SIZE-1);
//
// Set the port number in the address structure
//
AtoH((char *)&atmroot.satm_number.Addr[ATM_ADDR_SIZE-1], szPort, 1);
//
// Fill in the rest of the SOCKADDR_ATM structure
//
atmroot.satm_family = AF_ATM;
atmroot.satm_number.AddressType = ATM_NSAP;
atmroot.satm_number.NumofDigits = ATM_ADDR_SIZE;
atmroot.satm_blli.Layer2Protocol = SAP_FIELD_ANY;
atmroot.satm_blli.Layer3Protocol = SAP_FIELD_ABSENT;
atmroot.satm_bhli.HighLayerInfoType = SAP_FIELD_ABSENT;
//
// Print out what we're binding to and bind()
//
if (WSAAddressToString((LPSOCKADDR)&atmroot,
sizeof(atmroot), lpSocketProtocol, szAddr,
&dwAddrLen))
{
printf("WSAAddressToString failed: %d\n",
WSAGetLastError());
}
printf("Binding to: <%s>\n", szAddr);
if (bind(s, (SOCKADDR *)&atmroot,
sizeof(SOCKADDR_ATM)) == SOCKET_ERROR)
{
printf("bind() failed: %d\n", WSAGetLastError());
return;
}
// Invite each leaf
//
for(i=0; i < dwAddrCount ;i++)
{
// Fill in the SOCKADR_ATM structure for each leaf
//
memset(&atmleaf, 0, sizeof(SOCKADDR_ATM));
AtoH((char *)&atmleaf.satm_number.Addr[0], szLeafAddresses[i],
ATM_ADDR_SIZE-1);
AtoH((char *)&atmleaf.satm_number.Addr[ATM_ADDR_SIZE-1], szPort,
1);
atmleaf.satm_family = AF_ATM;
atmleaf.satm_number.AddressType = ATM_NSAP;
atmleaf.satm_number.NumofDigits = ATM_ADDR_SIZE;
atmleaf.satm_blli.Layer2Protocol = SAP_FIELD_ANY;
atmleaf.satm_blli.Layer3Protocol = SAP_FIELD_ABSENT;
atmleaf.satm_bhli.HighLayerInfoType = SAP_FIELD_ABSENT;
//
// Print out clients address and the invite it
//
if (WSAAddressToString((LPSOCKADDR)&atmleaf,
sizeof(atmleaf), lpSocketProtocol, szAddr,
&dwAddrLen))
{
printf("WSAAddressToString failed: %d\n",
WSAGetLastError());
}
printf("[%02d] Inviting: <%s>\n", i, szAddr);
if ((sLeafSock[i] = WSAJoinLeaf(s,
(SOCKADDR *)&atmleaf, sizeof(SOCKADDR_ATM), NULL,
NULL, NULL, NULL, JL_SENDER_ONLY))
== INVALID_SOCKET)
{
printf("WSAJoinLeaf() failed: %d\n",
WSAGetLastError());
WSACleanup();
return;
}
}
// Note that the ATM protocol is a bit different that TCP.
// When the WSAJoinLeaf (or connect call) completes the
// peer has not necessarily accepted the connection yet
// so immediately sending data will result in an error
// which is why we wait a short bit.
//
printf("Press a key to start sending.");
getchar();
printf("\n");
//
// Now send some data to the group address which will
// be replicated to all clients
//
wsasend.buf = sendbuf;
wsasend.len = 128;
for(i=0; i < dwDataCount ;i++)
{
memset(sendbuf, 'a' + (i%26), 128);
ret = WSASend(s, &wsasend, 1, &dwBytesSent, 0, NULL,
NULL);
if (ret == SOCKET_ERROR)
{
printf("WSASend() failed: %d\n", WSAGetLastError());
break;
}
printf("[%02d] Wrote: %d bytes\n", i, dwBytesSent);
Sleep(500);
}
for(i=0; i < dwAddrCount ;i++)
closesocket(sLeafSock[i]);
return;
}
//
// Function: Client
//
// Description:
// The client binds to the local interface (either one specified
// on the command line or the first local ATM address). It
// then waits on an accept call for the root invitation. It
// then waits to receive data.
//
void Client(SOCKET s, WSAPROTOCOL_INFO *lpSocketProtocol)
{
SOCKET sl;
SOCKADDR_ATM atm_leaf,
atm_root;
DWORD dwNumInterfaces,
dwBytesRead,
dwAddrLen=BUFSIZE,
dwFlags,
i;
WSABUF wsarecv;
char recvbuf[BUFSIZE],
szAddr[BUFSIZE];
int iLen = sizeof(SOCKADDR_ATM),
ret;
// Setup the local interface
//
memset(&atm_leaf, 0, sizeof(SOCKADDR_ATM));
if (!bLocalAddress)
{
dwNumInterfaces = GetNumATMInterfaces(s);
GetATMAddress(s, 0, &atm_leaf.satm_number);
}
else
AtoH((char *)&atm_leaf.satm_number.Addr[0], szLocalAddress,
ATM_ADDR_SIZE-1);
AtoH((char *)&atm_leaf.satm_number.Addr[ATM_ADDR_SIZE-1],
szPort, 1);
//
// Fill in the SOCKADDR_ATM structure
//
atm_leaf.satm_family = AF_ATM;
atm_leaf.satm_number.AddressType = ATM_NSAP;
atm_leaf.satm_number.NumofDigits = ATM_ADDR_SIZE;
atm_leaf.satm_blli.Layer2Protocol = SAP_FIELD_ANY;
atm_leaf.satm_blli.Layer3Protocol = SAP_FIELD_ABSENT;
atm_leaf.satm_bhli.HighLayerInfoType = SAP_FIELD_ABSENT;
//
// Print the address we're binding to and bind
//
if (WSAAddressToString((LPSOCKADDR)&atm_leaf,
sizeof(atm_leaf), lpSocketProtocol, szAddr,
&dwAddrLen))
{
printf("WSAAddressToString failed: %d\n",
WSAGetLastError());
}
printf("Binding to: <%s>\n", szAddr);
if (bind(s, (SOCKADDR *)&atm_leaf, sizeof(SOCKADDR_ATM))
== SOCKET_ERROR)
{
printf("bind() failed: %d\n", WSAGetLastError());
return;
}
listen(s, 1);
//
// Wait for the invitation
//
memset(&atm_root, 0, sizeof(SOCKADDR_ATM));
if ((sl = WSAAccept(s, (SOCKADDR *)&atm_root, &iLen, NULL,
0)) == INVALID_SOCKET)
{
printf("WSAAccept() failed: %d\n", WSAGetLastError());
return;
}
printf("Received a connection!\n");
// Receive some data
//
wsarecv.buf = recvbuf;
for(i=0; i < dwDataCount ;i++)
{
dwFlags = 0;
wsarecv.len = BUFSIZE;
ret = WSARecv(sl, &wsarecv, 1, &dwBytesRead, &dwFlags,
NULL, NULL);
if (ret == SOCKET_ERROR)
{
printf("WSARecv() failed: %d\n", WSAGetLastError());
break;
}
if (dwBytesRead == 0)
break;
recvbuf[dwBytesRead] = 0;
printf("[%02d] READ %d bytes: '%s'\n", i, dwBytesRead,
recvbuf);
}
closesocket(sl);
return;
}
//
// Function: main
//
// Description:
// This function loads Winsock library, parses command line
// arguments, creates the appropriate socket (with the right
// root or leaf flags), and start the client or server
// functions depending on the specified flags.
//
int main(int argc, char **argv)
{
WSADATA wsd;
SOCKET s;
WSAPROTOCOL_INFO lpSocketProtocol;
DWORD dwFlags;
ValidateArgs(argc, argv);
//
// Load the Winsock library
//
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
printf("WSAStartup failed\n");
return -1;
}
// Find an ATM capable protocol
//
if (FindProtocol(&lpSocketProtocol) == FALSE)
{
printf("Unable to find ATM protocol entry!\n");
return -1;
}
// Create the socket using the appripriate root or leaf flags
//
if (bServer)
dwFlags = WSA_FLAG_OVERLAPPED | WSA_FLAG_MULTIPOINT_C_ROOT |
WSA_FLAG_MULTIPOINT_D_ROOT;
else
dwFlags = WSA_FLAG_OVERLAPPED | WSA_FLAG_MULTIPOINT_C_LEAF |
WSA_FLAG_MULTIPOINT_D_LEAF;
if ((s = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,
FROM_PROTOCOL_INFO, &lpSocketProtocol, 0,
dwFlags)) == INVALID_SOCKET)
{
printf("socket failed with: %d\n", WSAGetLastError());
WSACleanup();
return -1;
}
// Start the correct driver depending on what flags were
// supplied on the command line.
//
if (bServer)
{
Server(s, &lpSocketProtocol);
}
else
{
Client(s, &lpSocketProtocol);
}
closesocket(s);
WSACleanup();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -