Code:
/************************** Receiver *************************/
// Module Name: Receiver.c
//
// Description:
// This sample receives UDP datagrams by binding to the specified
// interface and port number and then blocking on a recvfrom()
// call
/************************** Receiver *************************/
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdbool.h>
#include <sys/types.h> // data types
#include "sys/socket.h"
#include <netinet/in.h> // internet address family
#include <arpa/inet.h> // internet operations
typedef unsigned long DWORD;
using namespace std;
int iPort = 1234; // Port to receive on
DWORD dwCount, // Number of messages to read
dwLength; // Length of receiving buffer
int packet_length,
remainder;
bool bInterface = true; // Use an interface other than default
char* szInterface; // Interface to read datagrams from
char* multicast_grp_add;
char* multicast_src_add;
char* filename_video;
string filename_video_seq;
char* filename_file;
char* filename_count;
int max_burst_length = 0;
int current_burst_length = 0;
int prev_index = 0;
int current_index = 0;
#define DWL 1316
//********************************************************************
// Function: SetArgs
// Description: Set Global Parameters
//********************************************************************
void SetArgs()
{
dwCount = 1298; //-c
dwLength = 1316; //-l
szInterface = "192.168.0.3"; //-i
multicast_grp_add = "236.0.0.5"; //-g
multicast_src_add = "192.168.2.2"; //-s
filename_video = "video_out.mp4"; //-v
filename_video_seq = "seq_video_out.mp4";
filename_file = "file_out.txt"; //-f
filename_count = "count_out.txt"; //-t
packet_length = dwLength - 6;
remainder = 174; //-r
}
//********************************************************************
//********************************************************************
// Function: ValidateArgs
//********************************************************************
// Description:
// Parse the command line arguments, and set some global flags to
// indicate what actions to perform
//********************************************************************
void ParseArgs(int argc, char* argv[])
{
SetArgs();
for (int i = 1; i < argc; i++)
{
if ((*(argv[i]+1) == 'c') || (*(argv[i]+1) == 'C'))
{
// the number of packets to receive
cout << "the number of packets to receive" << endl;
dwCount = atol(argv[i+1]);
cout << dwCount << endl;
}
else if ((*(argv[i]+1) == 'l') || (*(argv[i]+1) == 'L'))
{
// the number of characters to receive
cout << "set dwLength" << endl;
dwLength = atol(argv[i+1]);
cout << dwLength << endl;
cout << "set packet_length" << endl;
packet_length = dwLength - 6;
cout << packet_length << endl;
}
else if ((*(argv[i]+1) == 'r') || (*(argv[i]+1) == 'R'))
{
// Remainder
cout << "Remainder" << endl;
remainder = atol(argv[i+1]);
cout << remainder << endl;
}
else if ((*(argv[i]+1) == 'i') || (*(argv[i]+1) == 'I'))
{
// Interface of the current receiver
cout << "set interface" << endl;
szInterface = argv[i+1];
cout << szInterface << endl;
}
else if ((*(argv[i]+1) == 'g') || (*(argv[i]+1) == 'G'))
{
// multicast group address
cout << "set multicast group address" << endl;
multicast_grp_add = argv[i+1];
cout << multicast_grp_add << endl;
}
else if ((*(argv[i]+1) == 's') || (*(argv[i]+1) == 'S'))
{
// multicast source address
cout << "set multicast source address" << endl;
multicast_src_add = argv[i+1];
cout << multicast_src_add << endl;
}
else if ((*(argv[i]+1) == 'v') || (*(argv[i]+1) == 'V'))
{
// video file path
cout << "set video" << endl;
filename_video = argv[i+1];
cout << filename_video << endl;
filename_video_seq = filename_video;
filename_video_seq.insert(0, "seq_");
cout << filename_video_seq << endl;
}
else if ((*(argv[i]+1) == 'f') || (*(argv[i]+1) == 'F'))
{
// file path
cout << "set file" << endl;
filename_file = argv[i+1];
cout << filename_file << endl;
}
else if ((*(argv[i]+1) == 't') || (*(argv[i]+1) == 'T'))
{
// count path
cout << "set count" << endl;
filename_count = argv[i+1];
cout << filename_count << endl;
}
i++;
}
}
//********************************************************************
//********************************************************************
//
// Function: main
//********************************************************************
// Description:
// Main thread of execution. Initialize Winsock, parse the command
// line arguments, create a socket, bind it to a local interface
// and port, and then read datagrams.
int main(int argc, char* argv[])
{
int s;
int ret, i, n;
int count; // Keeps track of the number of packets received
char count_s[50];
DWORD index_dw;
char index[7];
struct sockaddr_in sender,local;
socklen_t dwSenderSize;
// Multicast
struct ip_mreq imr;
char * str_rx_total;
size_t total_b;
//********************************************************************//
// Parse arguments
//********************************************************************//
ParseArgs(argc, argv);
//********************************************************************//
ofstream out_video(filename_video, ios::out|ios::binary);
// out_video will store packets exactly as received
ofstream out_video_seq(filename_video_seq.c_str(), ios::out|ios::binary);
// out_video_seq will store packets according to the index
ofstream out_file(filename_file, ios::out);
ofstream out_count(filename_count, ios::out);
// total bytes to receive
total_b = packet_length*(dwCount-1)+ remainder;
str_rx_total = new (nothrow) char [total_b];
if (!str_rx_total)
{
// error assigning memory to str_rx_total
printf ("Error in creating str_rx_total\n");
scanf("%*c");
return 1;
}
cout << total_b << endl;
// set all values in str_rx_total to zero
memset(str_rx_total, 0, total_b);
if (out_video && out_video_seq && out_file && out_count)
{
//********************************************************************//
// Create the socket
//********************************************************************//
s = socket(AF_INET, SOCK_DGRAM, 0);
if (s<0)
{
printf("socket() failed");
scanf("%*c");
out_video.close();
out_video_seq.close();
out_file.close();
out_count.close();
return 1;
}
cout << "socket success" << endl;
//********************************************************************//
int reuse = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof (reuse))<0)
{
perror("Setting SO_REUSEADDR error");
close(s);
exit(1);
}
else
printf("Setting SO_REUSEADDR...OK.\n");
//********************************************************************//
// Bind the socket to an interface
//********************************************************************//
local.sin_family = AF_INET;
local.sin_port = htons((short)iPort);
if (bInterface)
{
local.sin_addr.s_addr = inet_addr(szInterface);
}
else
{
local.sin_addr.s_addr = htonl(INADDR_ANY);
}
if (bind(s, (struct sockaddr *)&local, sizeof(local)) < 0)
{
printf("bind() failed");
scanf("%*c");
out_video.close();
out_video_seq.close();
out_file.close();
out_count.close();
return 1;
}
cout << "bind success" << endl;
imr.imr_interface.s_addr = inet_addr(szInterface);
// the interface of the receiver - ip address of the receiver
imr.imr_multiaddr.s_addr = inet_addr(multicast_grp_add);
// ip address of the multicast group
if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&imr, sizeof(imr)) < 0)
{
printf("Problem");
scanf ("%*c");
out_video.close();
out_video_seq.close();
out_file.close();
out_count.close();
return 1;
}
//********************************************************************//
cout << "set socket ok" << endl;
//********************************************************************//
// Allocate the receive buffer
//********************************************************************//
char recvbuf[DWL];
//********************************************************************//
//********************************************************************//
// Read the datagrams
//********************************************************************//
count = 0;
char * str_rx;
str_rx = new (nothrow) char [packet_length];
if (str_rx != 0)
{
for(i = 0; i < dwCount+3; i++)
// +3 to include the quit signals
{
dwSenderSize = sizeof(sender);
cout << "before read" << endl;
int received = 0;
if ((received = recvfrom(s, &recvbuf, dwLength, 0, (struct sockaddr *)&sender, &dwSenderSize)) < 0)
{
printf("recvfrom() failed;\n");
scanf("%*c");
break;
}
else if (received == 0)
break;
else
// received something
// processing what was received
{
cout << "after read" << endl;
recvbuf[received] = '\0';
// output on screen
printf("[%s] sent me:\n", inet_ntoa(sender.sin_addr));
// append to out_file the index of the current packet
for (int i = 0; i < 6; i++)
{
index[i] = *(recvbuf+i);
}
index[6] = '\n';
out_file.write(index, 7);
index_dw = atoi(index);
//printf("index_dw = %d\n", index_dw);
printf("index_dw = %lu\n", index_dw);
if (index_dw != 111111)
{ // not quit signal
count++;
printf("total packets received: %d\n", count);
n = sprintf(count_s, "total received packets: %d\n", count);
out_count.write(count_s, n);
current_index = index_dw;
current_burst_length = current_index - prev_index;
if (current_burst_length > max_burst_length)
{
// update variables
max_burst_length = current_burst_length;
}
prev_index = current_index;
// creating the video
if (index_dw == dwCount-1)
{
// receive the last packet
// therefore require only 'remainder' characters
char * str_rx_remainder;
str_rx_remainder = new (nothrow) char [remainder];
if (str_rx_remainder != 0)
{
for (int index = 0; index < remainder; index++)
{
*(str_rx_remainder+index) = *(recvbuf+6+index);
// 6 being the number of characters dedicated to the
// sequence number of the packet
// update str_rx_total
*(str_rx_total+(index_dw*packet_length)+index) = *(recvbuf+6+index);
}
printf("Extract %d\n", remainder);
out_video.write(str_rx_remainder, remainder);
}
else
{
// memory was not assigned correctly
cout << "Error in assigning str_rx_remainder" << endl;
scanf("%*c");
out_file.close();
out_video.close();
out_count.close();
exit(1);
}
}
else
{
// use all characters except the first 6 characters
for (int index = 0; index < packet_length; index++)
{
*(str_rx+index) = *(recvbuf+6+index);
// 6 being the number of characters dedicated to the
// sequence number of the packet
//update str_rx_total
*(str_rx_total+(index_dw*packet_length)+index) = *(recvbuf+6+index);
}
out_video.write(str_rx, packet_length);
}
}
else
{
// quit signal
// must exit
//closesocket(s);
close(s);
out_video_seq.write(str_rx_total, total_b);
out_video.close();
out_video_seq.close();
out_file.close();
out_count.close();
printf("max burst length: %d\n", max_burst_length);
printf("exiting: please press any key");
scanf("%*c");
// WSACleanup();
return 0;
}
}
}
}
else
{
// memory was not assigned correctly
cout << "Error in assigning str_rx" << endl;
scanf("%*c");
out_video.close();
out_video_seq.close();
out_file.close();
out_count.close();
return 1;
}
close(s);
out_file.close();
out_count.close();
out_video.close();
out_video_seq.write(str_rx_total, total_b);
out_video_seq.close();
scanf("%*c");
return 0;
}
else
{
// did not open the files correctly
printf ("Problem opening files");
scanf ("%*c");
exit (1);
}
}
/************************* End of Receiver **********************/