Issue
I have one server and one client. The server and client have 2 NICs. This is being developed on Fedora 26.
- Server IPs and ports: 10.0.0.209:21323 (data channel) and 10.0.0.121:8080 (control channel)
- Client IPs and ports: 10.0.0.210:21323 (data channel) and 10.0.0.122:8080 (control channel)
I am sending a buffer from the client containing a packet number (qualitySequenceCounter) and 40 bytes of an encoded audio file (.chn) over my "data channel" 10.0.0.210:21323 -> 10.0.0.209:21323. When the server receives the data, it unpacks the qualitySequenceCounter and the audio data. Then the server is supposed to send the qualitySequenceCounter back to the client over the "control channel" 10.0.0.121:8080 -> 10.0.0.122:8080. The server sends the data over the "control channel" but the client never receives it and just hangs there waiting. I can't figure out what I'm missing or doing wrong.
Server
// server2s.cpp
// parsing files
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
//network stuff
#include <sys/socket.h>
#include <netdb.h>
#include <memory.h>
#include <stdio.h>
#include <stdarg.h>
//#define SOL_IP IPPROTO_IP
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#endif
#define sockerrno errno
char szLineBuf[500];
int iNetSock = INVALID_SOCKET;
int iRequest = 1;
struct sockaddr_in sAddr, cAddr;
socklen_t iAddrLen = sizeof(sAddr);
socklen_t cAddrLen = sizeof(cAddr);
int perr(const char *pszFormat, ...)
{
va_list argList;
va_start(argList, pszFormat);
vsnprintf(szLineBuf, sizeof(szLineBuf)-10, pszFormat, argList);
szLineBuf[sizeof(szLineBuf)-10] = '\0';
printf("Error: %s\n", szLineBuf);
return 0;
}
//++++++++++++++++++++++++++++++++++++++
// second socket for control channel
char szLineBufCC[500];
int iNetSockCC = INVALID_SOCKET;
int iRequestCC = 1;
struct sockaddr_in sAddrCC, cAddrCC;
socklen_t iAddrLenCC = sizeof(sAddrCC);
socklen_t cAddrLenCC = sizeof(cAddrCC);
int perrCC(const char *pszFormat, ...)
{
va_list argList;
va_start(argList, pszFormat);
vsnprintf(szLineBufCC, sizeof(szLineBufCC)-10, pszFormat, argList);
szLineBufCC[sizeof(szLineBufCC)-10] = '\0';
printf("Error CC: %s\n", szLineBufCC);
return 0;
}
// end
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int main(int argc, const char * argv[]) {
//file I/O stuff
// this is the char array that we will populate with the control channel counter and audio data
char buffer[44];
// buffer used only for audio data to be written to file
char audioBuffer[40];
// this is the char array for the control channel counter
char bufferCC[4];
// this is for opening the audio file
std::ifstream inFile;
std::ofstream outFile;
// initializing the location of the audio channel read
long fileLoc = 0;
// initializing the control channel counter
int qualitySequenceCounter=0;
// initializing how we will be able to tell where we are in the audio file; need to add code to loop back to beginning of the audio file once we reach the end
struct stat results;
//network stuff
const char *pszHost = "10.0.0.209";
unsigned short iPort = 21323;
//+++++++++++++++++++++++++++++++++++++++
// second socket for control channel
//network stuff
const char *pszHostCC = "10.0.0.121";
unsigned short iPortCC = 8080;
// end
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//open up audio file for parsing
outFile.open("/home/mode1_received.chn", std::ios::out | std::ios::binary);
//if the file doesn't open, tell me
if(!outFile.is_open()){
std::cout << "Error opening audio file\n";
}
if (stat("/home/mode1_received.chn", &results) == 0) {
// The size of the file in bytes is in
// results.st_size
std::cout << "File size:" << results.st_size << "\n";
}
else {
std::cout << "An error occured getting the file length";
// An error occurred
}
//establish the IP component
memset((char *)&sAddr, 0,sizeof(sAddr));
memset((char *)&cAddr, 0,sizeof(cAddr));
sAddr.sin_family = AF_INET;
sAddr.sin_port = htons(iPort);
struct hostent *pHost = gethostbyname(pszHost);
memcpy(&sAddr.sin_addr.s_addr, pHost->h_addr, pHost->h_length);
//creates the UDP socket to send data to
if ((iNetSock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return 9+perr("cannot create socket");
// Bind the socket with the server address
if ( bind(iNetSock, (const struct sockaddr *)&sAddr,
sizeof(sAddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
//++++++++++++++++++++++++++++++++++++++
// second socket for CC
//establish the IP component
memset((char *)&sAddrCC, 0,sizeof(sAddrCC));
memset((char *)&cAddrCC, 0,sizeof(cAddrCC));
sAddrCC.sin_family = AF_INET;
sAddrCC.sin_port = htons(iPortCC);
struct hostent *pHostCC = gethostbyname(pszHostCC);
memcpy(&sAddrCC.sin_addr.s_addr, pHostCC->h_addr, pHostCC->h_length);
//creates the UDP socket to send data to
if ((iNetSockCC = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return 9+perrCC("cannot create socket for CC: Control Channel");
// Bind the socket with the server address
if ( bind(iNetSockCC, (const struct sockaddr *)&sAddrCC,
sizeof(sAddrCC)) < 0 )
{
perror("bind failed for CC");
exit(EXIT_FAILURE);
}
// End
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// divide size of audio file by 40
while(qualitySequenceCounter < 103574){
// Get data
unsigned int n;
socklen_t len = sizeof(cAddr);
//char *pData = &buffer[0];
n = recvfrom(iNetSock, (char *)buffer, 44,
MSG_WAITALL, ( struct sockaddr *) &cAddr,
&len);
printf("data received\n");
memcpy(&qualitySequenceCounter, buffer, sizeof(int));
memcpy(&audioBuffer, &buffer[4], 40);
printf("qualitySequenceCounter : %u\n", qualitySequenceCounter);
// this copies our counter that we are using for the feedback loop into the 4 byte char array
memcpy(&bufferCC[0], (char *)&(qualitySequenceCounter), sizeof(int));
// this sets up the payload for the UDP transmission
//char *pDataCC = &bufferCC[0];
// sending the data via UDP
sendto(iNetSockCC, bufferCC, 4, 0, (struct sockaddr *)&cAddrCC, cAddrLenCC);
printf("data sent back\n");
// this code allows us to check the counter by printing it to std out
/*int counterCheck = *((int *)buffer);
std::cout << "Counter check: " << counterCheck << "\n";
const char* beg = buffer;
const char* end = beg + sizeof(buffer);
while(beg != end)
std::cout << std::bitset<8>(*beg++) << ' ';
std::cout << '\n';
*/
//printf("qualitySequenceCounter : %u\n", qualitySequenceCounter);
//if (buffer == NULL)
// break;
outFile << audioBuffer;
//buffer[n] = '\0';
//printf("Client : %s\n", pData);
//printf("Client : %u\n", n);
// qualcounter is 103574
// will need to reset the fileLoc counter to 0 once we reach the end of the audio file to loop the demo
}
//close output file
outFile.close();
return 0;
}
Client
// client2s.cpp
// parsing files
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
//network stuff
#include <sys/socket.h>
#include <netdb.h>
#include <memory.h>
#include <stdio.h>
#include <stdarg.h>
//#define SOL_IP IPPROTO_IP
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#endif
#define sockerrno errno
char szLineBuf[500];
int iNetSock = INVALID_SOCKET;
int iRequest = 1;
struct sockaddr_in sAddr;
socklen_t iAddrLen = sizeof(sAddr);
int perr(const char *pszFormat, ...)
{
va_list argList;
va_start(argList, pszFormat);
vsnprintf(szLineBuf, sizeof(szLineBuf)-10, pszFormat, argList);
szLineBuf[sizeof(szLineBuf)-10] = '\0';
printf("Error: %s\n", szLineBuf);
return 0;
}
//++++++++++++++++++++++++++++++++++++++++
// second socket for control channel
char szLineBufCC[500];
int iNetSockCC = INVALID_SOCKET;
int iRequestCC = 1;
struct sockaddr_in sAddrCC;
socklen_t iAddrLenCC = sizeof(sAddrCC);
int perrCC(const char *pszFormat, ...)
{
va_list argList;
va_start(argList, pszFormat);
vsnprintf(szLineBufCC, sizeof(szLineBufCC)-10, pszFormat, argList);
szLineBufCC[sizeof(szLineBufCC)-10] = '\0';
printf("Error with CC: %s\n", szLineBufCC);
return 0;
}
// End
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
int main(int argc, const char * argv[]) {
//file I/O stuff
// this is the char array that we will populate with the control channel counter and audio data
char buffer[44];
// this is the char array for the control channel counter
char bufferCC[4];
// this is for opening the audio file
std::ifstream inFile;
// initializing the location of the audio channel read
long fileLoc = 0;
// initializing the control channel counter
int qualitySequenceCounter=0;
// counter received over control channel CC
int qualityCC=0;
// initializing how we will be able to tell where we are in the audio file; need to add code to loop back to beginning of the audio file once we reach the end
struct stat results;
//network stuff
const char *pszHost = "10.0.0.209";
unsigned short iPort = 21323;
//++++++++++++++++++++++++++++++++++++++++
// second socket for control channel
//network stuff
const char *pszHostCC = "10.0.0.121";
unsigned short iPortCC = 8080;
// End
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//open up audio file for parsing
inFile.open("/home/mode1.chn", std::ios::in | std::ios::binary);
//if the file doesn't open, tell me
if(!inFile.is_open()){
std::cout << "Error opening audio file\n";
}
if (stat("/home/mode1.chn", &results) == 0)
// The size of the file in bytes is in
// results.st_size
std::cout << "File size:" << results.st_size << "\n";
else
std::cout << "An error occured getting the file length";
// An error occurred}
//establish the IP component
memset((char *)&sAddr, 0,sizeof(sAddr));
sAddr.sin_family = AF_INET;
sAddr.sin_port = htons(iPort);
struct hostent *pHost = gethostbyname(pszHost);
memcpy(&sAddr.sin_addr.s_addr, pHost->h_addr, pHost->h_length);
//creates the UDP socket to send data to
if ((iNetSock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return 9+perr("cannot create socket");
//++++++++++++++++++++++++++++++++++++
// second socket for control channel
//establish the IP component
memset((char *)&sAddrCC, 0,sizeof(sAddrCC));
sAddrCC.sin_family = AF_INET;
sAddrCC.sin_port = htons(iPortCC);
struct hostent *pHostCC = gethostbyname(pszHostCC);
memcpy(&sAddrCC.sin_addr.s_addr, pHostCC->h_addr, pHostCC->h_length);
//creates the UDP socket to send data to
if ((iNetSockCC = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return 9+perrCC("cannot create socket for Control Channel");
// End
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
while(qualitySequenceCounter < results.st_size && fileLoc >= 0){
// will need to open file inside the while loop once we add the control channel feedback, else we need to open all of the different files at once (which might be easier) and switch back and forth between multiple open files
// this reads in 40 bytes of data and places it 4 bytes into the char array
inFile.read(&buffer[4],40);
// getting the location of where we are in the audio file in case we need to switch audio files
fileLoc = inFile.tellg();
// this copies our counter that we are using for the feedback loop into the first 4 bytes of the char array
memcpy(&buffer[0], (char *)&(qualitySequenceCounter), sizeof(int));
// this sets up the payload for the UDP transmission
char *pData = &buffer[0];
// sending the data via UDP
sendto(iNetSock, pData, 44, 0, (struct sockaddr *)&sAddr, iAddrLen);
printf("data sent\n");
//++++++++++++++++++++++++++++++++++++
// second socket for control channel
// Get data
unsigned int nCC;
socklen_t lenCC = sizeof(sAddrCC);
//char *pData = &buffer[0];
nCC = recvfrom(iNetSockCC, (char *)bufferCC, 4,
MSG_WAITALL, ( struct sockaddr *) &sAddrCC,
&lenCC);
printf("data received again\n");
memcpy(&qualityCC, bufferCC, sizeof(int));
printf("qualityCC : %u\n", qualityCC);
// End
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// increment the feedback counter for the control channel
qualitySequenceCounter++;
// this code allows us to check the counter by printing it to std out
/* int counterCheck = *((int *)buffer);
std::cout << "Counter check: " << counterCheck << "\n";
const char* beg = buffer;
const char* end = beg + sizeof(buffer);
while(beg != end)
std::cout << std::bitset<8>(*beg++) << ' ';
std::cout << '\n';
*/
// will need to reset the fileLoc counter to 0 once we reach the end of the audio file to loop the demo
}
//close input file
inFile.close();
return 0;
}
Solution
The client never binds iNetSockCC
to any particular port, so it isn't listening on any particular port. So how can it receive the response from the server? I'm kind of puzzled why you want two pairs of sockets though. Why not just have the server reply to the client by sending back to the source?
Answered By - David Schwartz Answer Checked By - David Marino (WPSolving Volunteer)