int __cdecl main() { WSADATA wsd; INT i = 0, nErr = 0, nStartup = 0, rc = 0; SOCKET sock = INVALID_SOCKET; SOCKADDR_STORAGE addr = {0}, mcaddr = {0}, remoteaddr = {0}; WSAOVERLAPPED over = {0}; WSABUF wsabuf = {0}; DWORD dwBytes = 0, dwFlags = 0, dwRet = 0; IPV6_MREQ mreq = {0}; WSAMSG wsamsg = {0}; LPFN_WSARECVMSG WSARecvMsg = NULL; __try { //Initialize Winsock nErr = WSAStartup(WS_VER,&wsd); if (nErr) { WSASetLastError(nErr); ERR("WSAStartup"); __leave; } else nStartup++; // bind socket and register multicast mcaddr.ss_family = AF_INET6; InitMcastAddr((SOCKADDR*)&mcaddr,sizeof mcaddr); if (INVALID_SOCKET == (sock = socket(AF_INET6,SOCK_DGRAM,0))) { ERR("socket"); __leave; } if(!RouteLookup((SOCKADDR*)&mcaddr, sizeof mcaddr, (SOCKADDR*)&addr, sizeof addr )) { ERR("RouteLookup"); __leave; } SET_PORT((SOCKADDR*)&addr,DEFAULT_PORT); if (SOCKET_ERROR == bind(sock,(SOCKADDR*)&addr,sizeof addr)) { ERR("bind"); __leave; } mreq.ipv6mr_multiaddr = ((SOCKADDR_IN6*)&mcaddr)->sin6_addr; if (SOCKET_ERROR == setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*)&mreq, sizeof mreq )) { ERR("setsockopt IPV6_ADD_MEMBRESHIP"); __leave; } // PktInfo if (!SetIpv6PktInfoOption(sock)) { ERR("SetIpv6PktInfoOption"); __leave; } if(!AllocAndInitIpv6PktInfo(&wsamsg)) { ERR("AllocAndInitIpv6PktInfo"); __leave; } // data buffer wsabuf.buf = (CHAR*)MALLOC(100); if(NULL == wsabuf.buf) { ERR("HeapAlloc"); __leave; } wsabuf.len = (ULONG)MSIZE(wsabuf.buf); wsamsg.lpBuffers = &wsabuf; wsamsg.dwBufferCount = 1; // packet source address wsamsg.name = (SOCKADDR*)&remoteaddr; wsamsg.namelen = sizeof remoteaddr; //Post overlapped WSARecvMsg InitOverlap(&over); if (NULL == (WSARecvMsg = GetWSARecvMsgFunctionPointer())) { ERR("GetWSARecvMsgFunctionPointer"); __leave; } if (SOCKET_ERROR == WSARecvMsg(sock, &wsamsg, &dwBytes, &over, NULL )) { if (WSA_IO_PENDING != WSAGetLastError()) { ERR("WSARecvMsg"); __leave; } } //set send interface if (SOCKET_ERROR == SetSendInterface(sock,(SOCKADDR*)&addr)) { ERR("SetSendInterface"); __leave; } //send msg to multicast SET_PORT((SOCKADDR*)&mcaddr,DEFAULT_PORT); //send a few packets for (i=0; i<5; i++) { if (SOCKET_ERROR == (rc = sendto(sock, TST_MSG, lstrlenA(TST_MSG), 0, (SOCKADDR*)&mcaddr, sizeof (mcaddr) ))) { ERR("sendto"); __leave; } printf("Sent %d bytes\n",rc); } dwRet = WaitForSingleObject(over.hEvent,DEFAULT_WAIT); if (dwRet) { printf("%s\n",gai_strerror(dwRet)); __leave; } if (!WSAGetOverlappedResult(sock, &over, &dwBytes, TRUE, &dwFlags )) { ERR("WSAGetOverlappedResult"); __leave; } printf("WSARecvMsg completed with %d bytes\n",dwBytes); // if multicast packet do further processing if (MSG_MCAST & wsamsg.dwFlags) { if (ProcessIpv6Msg(&wsamsg)) { //do something more interesting here printf("Recvd multicast msg.\n"); } } } __finally { CLOSESOCK(sock); FREE(wsabuf.buf); FREE(wsamsg.Control.buf); CLOSESOCKEVENT(over.hEvent); if(nStartup) WSACleanup(); } return 0; }
// // Function: main // // Description: // Parse the command line arguments, load the Winsock library, // create a socket and join the multicast group. If set as a // sender then begin sending messages to the multicast group; // otherwise, call recvfrom() to read messages send to the // group. // int _cdecl main(int argc, char **argv) { WSADATA wsd; SOCKET s, sc; SOCKADDR_STORAGE remote; struct addrinfo *resmulti=NULL, *resif=NULL, *resbind=NULL; char *buf=NULL; int remotelen, err, rc, i=0; // Parse the command line ValidateArgs(argc, argv); // Load Winsock if (WSAStartup(MAKEWORD(1, 1), &wsd) != 0) { printf("WSAStartup failed\n"); return -1; } // Resolve the multicast address resmulti = ResolveAddress(gMulticast, gPort, AF_INET, 0, 0); if (resmulti == NULL) { fprintf(stderr, "Unable to convert multicast address '%s': %d\n", gMulticast, WSAGetLastError()); return -1; } // // Create the socket. In Winsock 1 you don't need any special // flags to indicate multicasting. // s = socket(resmulti->ai_family, gSocketType, gProtocol); if (s == INVALID_SOCKET) { printf("socket failed with: %d\n", WSAGetLastError()); return -1; } printf("socket handle = 0x%p\n", s); // Allocate the send/receive buffer buf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, gBufferSize); if (buf == NULL) { fprintf(stderr, "HeapAlloc failed: %d\n", GetLastError()); return -1; } if (bSender) { // Bind to the wildcard address resbind = ResolveAddress(NULL, gPort, AF_INET, 0, 0); if (resbind == NULL) { fprintf(stderr, "Unable to obtain bind address!\n"); return -1; } // Bind the socket rc = bind(s, resbind->ai_addr, resbind->ai_addrlen); if (rc == SOCKET_ERROR) { fprintf(stderr, "bind failed: %d\n", WSAGetLastError()); return -1; } freeaddrinfo(resbind); // If sepcified, set the send interface if (gInterfaceCount == 1) { resif = ResolveAddress(gListenInterface[0], gPort, AF_INET, 0, 0); if (resif == NULL) { return -1; } rc = SetSendInterface(s, resif); freeaddrinfo(resif); // Set the TTL to something else. The default TTL is one. rc = SetMulticastTtl(s, resmulti->ai_family, gTtl); if (rc == SOCKET_ERROR) { return -1; } } // If specified set the late joiner option if (gLateJoin != -1) { SetLateJoin(s, gLateJoin); } // If specified set the window paramters if (bSetSendWindow) { SetWindowSize(s, gWindowSizeBytes, gWindowSizeMSec, gWindowRateKbitsSec); } // If specified set the FEC paramters if (bUseFec == TRUE) { SetFecParameters(s, gFecBlockSize, gFecGroupSize, bFecOnDemand, gFecProActive); } // Connect the socket to the multicast group the session is to be on rc = connect(s, resmulti->ai_addr, resmulti->ai_addrlen); if (rc == SOCKET_ERROR) { printf("connect failed: %d\n", WSAGetLastError()); return -1; } memset(buf, '^', gBufferSize); // Send some data for(i=0; i < gCount ; i++) { rc = send( s, buf, gBufferSize, 0 ); if (rc == SOCKET_ERROR) { fprintf(stderr, "send failed with: %d\n", WSAGetLastError()); return -1; } printf("SENT %d bytes\n", rc); } } else { // Bind the socket to the multicast address on which the session will take place rc = bind(s, resmulti->ai_addr, resmulti->ai_addrlen); if (rc == SOCKET_ERROR) { fprintf(stderr, "bind failed: %d\n", WSAGetLastError()); return -1; } printf("Binding to "); PrintAddress(resmulti->ai_addr, resmulti->ai_addrlen); printf("\n"); // Add each supplied interface as a receive interface if (gInterfaceCount > 0) { for(i=0; i < gInterfaceCount ;i++) { resif = ResolveAddress(gListenInterface[i], "0", AF_INET, 0, 0); if (resif == NULL) { return -1; } rc = AddReceiveInterface(s, resif); freeaddrinfo(resif); } } // Listen for sessions rc = listen(s, 1); if (rc == SOCKET_ERROR) { fprintf(stderr, "listen failed: %d\n", WSAGetLastError()); return -1; } // Wait for a session to become available remotelen = sizeof(remote); sc = accept(s, (SOCKADDR *)&remote, &remotelen); if (sc == INVALID_SOCKET) { fprintf(stderr, "accept failed: %d\n", WSAGetLastError()); return -1; } printf("Join multicast session from: "); PrintAddress((SOCKADDR *)&remote, remotelen); printf("\n"); while (1) { // Receive data until an error or until the session is closed rc = recv(sc, buf, gBufferSize, 0); if (rc == SOCKET_ERROR) { if ((err = WSAGetLastError()) != WSAEDISCON) { fprintf(stderr, "recv failed: %d\n", err); } break; } else { printf("received %d bytes\n", rc); } } // Close the session socket closesocket(sc); } // Clean up freeaddrinfo(resmulti); closesocket(s); WSACleanup(); return 0; }