Related
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;
}
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?
These are current working versions of the code that solve the question I posted using the advice of David Schwartz (See comments on the question above).
This is being developed on a MacBook Pro using two virtual machines running Fedora 26. Then it is further tested on a private network with separate laptops running Fedora 26. Wireshark and netem have been indispensable.
Server (s2.cpp)
// Server
// s2.cpp
// Created by JParks on 7/12/19.
// Last edit: Thur, Sept 5, 3:19PM 2019
//parsing files
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
//network stuff
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory.h>
#include <stdio.h>
#include <stdarg.h>
#include <thread>
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#endif
#define sockerrno errno
char szLineBuf[500];
char szLineBufCC[500];
//char buffer[44];
// Server data interface: enp0s3
const char *server_data_channel_ip = "10.0.0.209";
// Server control interface: enp0s8
const char *server_control_channel_ip = "10.0.0.121";
// Client data interface: enp0s3
const char *client_data_channel_ip = "10.0.0.149";
// Client control interface: enp0s8
const char *client_control_channel_ip = "10.0.0.232";
// Ports for data and control channels
unsigned short dataPort = 21323;
unsigned short controlPort = 8080;
// Data Socket
int iNetSock = INVALID_SOCKET;
int iRequest = 1;
struct sockaddr_in sAddr, cAddr;
socklen_t sAddrLen = sizeof(sAddr);
socklen_t cAddrLen = sizeof(cAddr);
// Control Socket
int iNetSockCC = INVALID_SOCKET;
int iRequestCC = 1;
struct sockaddr_in sAddrCC, cAddrCC;
socklen_t sAddrLenCC = sizeof(sAddrCC);
socklen_t cAddrLenCC = sizeof(cAddrCC);
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;
}
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;
}
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[324];
// buffer used only for audio data to be written to file
char audioBuffer[320];
// 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;
//open up audio file for parsing
outFile.open("/home/jparks/Downloads/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/jparks/Downloads/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
}
//network stuff
// Data channel
const char *pszHost = server_data_channel_ip;
//establish the IP component
memset((char *)&sAddr, 0,sizeof(sAddr));
sAddr.sin_family = AF_INET;
sAddr.sin_addr.s_addr = inet_addr(server_data_channel_ip);
sAddr.sin_port = htons(dataPort);
struct hostent *pHost = gethostbyname(pszHost);
memcpy(&sAddr.sin_addr.s_addr, pHost->h_addr, pHost->h_length);
memset((char *)&cAddr, 0,sizeof(cAddr));
cAddr.sin_family = AF_INET;
cAddr.sin_addr.s_addr = inet_addr(client_data_channel_ip);
cAddr.sin_port = htons(dataPort);
//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
// Control Channel
const char *pszHostCC = server_control_channel_ip;
//establish the IP component
memset((char *)&sAddrCC, 0,sizeof(sAddrCC));
sAddrCC.sin_family = AF_INET;
sAddrCC.sin_addr.s_addr = inet_addr(server_control_channel_ip);
sAddrCC.sin_port = htons(controlPort);
struct hostent *pHostCC = gethostbyname(pszHostCC);
memcpy(&sAddrCC.sin_addr.s_addr, pHostCC->h_addr, pHostCC->h_length);
memset((char *)&cAddrCC, 0,sizeof(cAddrCC));
cAddrCC.sin_family = AF_INET;
cAddrCC.sin_addr.s_addr = inet_addr(client_control_channel_ip);
cAddrCC.sin_port = htons(controlPort);
//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);
}
//std::thread t1(task1, iNetSock, buffer, cAddr, cAddrLen, qualitySequenceCounter, audioBuffer);
// divide size of audio file by 320
// audio data file size: 4142984 -> divide by 320 to get number of packets ~= 12,945
// Audio needs to be decoded according to Steve's variation of codec G.711
while(qualitySequenceCounter < 12945){
// Get data
unsigned int n;
//socklen_t len = sizeof(cAddr);
//char *pData = &buffer[0];
n = recvfrom(iNetSock, (char *)buffer, 324,
MSG_WAITALL, ( struct sockaddr *) &cAddr,
&cAddrLen);
printf("data received\n");
memcpy(&qualitySequenceCounter, buffer, sizeof(int));
memcpy(&audioBuffer, &buffer[4], 320);
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 (c2.cpp)
// Client
// c2.cpp
// AudioParseSendReflect
// Last edit: Thur, Sept 5, 3:19PM 2019
//parsing files
#include <iostream>
#include <fstream>
#include <string>
#include <sys/stat.h>
//network stuff
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory.h>
#include <stdio.h>
#include <stdarg.h>
#include <thread>
#include <chrono>
#ifndef INVALID_SOCKET
#define INVALID_SOCKET -1
#endif
#define sockerrno errno
char szLineBuf[500];
char szLineBufCC[500];
// Client data interface: enp0s3
const char *client_data_channel_ip = "10.0.0.149";
// Client control interface: enp0s8
const char *client_control_channel_ip = "10.0.0.232";
// Server data interface: enp0s3
const char *server_data_channel_ip = "10.0.0.209";
// Server control interface: enp0s8
const char *server_control_channel_ip = "10.0.0.121";
// Ports for data and control channels
unsigned short dataPort = 21323;
unsigned short controlPort = 8080;
// Data Socket
int iNetSock = INVALID_SOCKET;
int iRequest = 1;
struct sockaddr_in sAddr, cAddr;
socklen_t sAddrLen = sizeof(sAddr);
socklen_t cAddrLen = sizeof(cAddr);
// Control Socket
int iNetSockCC = INVALID_SOCKET;
int iRequestCC = 1;
struct sockaddr_in sAddrCC, cAddrCC;
socklen_t sAddrLenCC = sizeof(sAddrCC);
socklen_t cAddrLenCC = sizeof(cAddrCC);
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;
}
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;
}
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[324];
// 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;
//open up audio file for parsing
inFile.open("/home/jparks/Downloads/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/jparks/Downloads/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
}
//network stuff
// Data Channel
const char *pszHost = client_data_channel_ip;
//establish the IP component
memset((char *)&sAddr, 0,sizeof(sAddr));
sAddr.sin_family = AF_INET;
sAddr.sin_addr.s_addr = inet_addr(server_data_channel_ip);
sAddr.sin_port = htons(dataPort);
memset((char *)&cAddr, 0,sizeof(cAddr));
cAddr.sin_family = AF_INET;
cAddr.sin_addr.s_addr = inet_addr(client_data_channel_ip);
cAddr.sin_port = htons(dataPort);
struct hostent *pHost = gethostbyname(pszHost);
memcpy(&cAddr.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 *)&cAddr,
sizeof(cAddr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
//++++++++++++++++++++++++++++++++++++
// second socket for control channel
// Control Channel
const char *pszHostCC = client_control_channel_ip;
//establish the IP component
memset((char *)&sAddrCC, 0,sizeof(sAddrCC));
sAddrCC.sin_family = AF_INET;
sAddrCC.sin_addr.s_addr = inet_addr(server_control_channel_ip);
sAddrCC.sin_port = htons(controlPort);
memset((char *)&cAddrCC, 0,sizeof(cAddrCC));
cAddrCC.sin_family = AF_INET;
cAddrCC.sin_addr.s_addr = inet_addr(client_control_channel_ip);
cAddrCC.sin_port = htons(controlPort);
struct hostent *pHostCC = gethostbyname(pszHostCC);
memcpy(&cAddrCC.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");
// Bind the socket with the server address
if ( bind(iNetSockCC, (const struct sockaddr *)&cAddrCC,
sizeof(cAddrCC)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
// audio data file size: 4142984 -> divide by 320 to get number of packets ~= 12,945
// audio is encoded using Steve's variation of codec G.711
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],320);
// 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];
//if(qualitySequenceCounter == 1000 || qualitySequenceCounter == 1001 || qualitySequenceCounter == 1002 ||qualitySequenceCounter == 1003) {
// printf("packet 1000 is dropped\n");
//qualitySequenceCounter++;
//} else {
// sending the data via UDP
sendto(iNetSock, pData, 324, 0, (struct sockaddr *)&sAddr, sAddrLen);
printf("data sent\n");
std::this_thread::sleep_for(std::chrono::nanoseconds(20000000));
printf("delay over\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,
&sAddrLenCC);
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;
}
I made a client server program by using C++.
I have a problem if I try to send large files. For example, a 50 byte file works fine while a 200 byte file fails.
Server Code:
// server.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int wsaerr;
wVersionRequested = MAKEWORD(2, 2);
wsaerr = WSAStartup(wVersionRequested, &wsaData);
if (wsaerr != 0) {
printf("The Winsock DLL not found \n ");
} else {
printf("The Winsock DLL found\n ");
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("not support Winsock version 2.2 ");
} else {
printf("support winsock version 2.2 \n ");
}
SOCKET m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == INVALID_SOCKET) {
printf("Error di socket(): %ld\n", WSAGetLastError());
WSACleanup();
} else{
printf("Socket() Berhasil ! \n");
}
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr("127.0.0.1");
service.sin_port = htons(55555);
int namelen = sizeof(service);
int m_bind = bind(m_socket, (sockaddr*)&service, namelen);
if (m_bind == SOCKET_ERROR){
printf("bind() failed ! %ld\n ", WSAGetLastError());
} else {
printf("bind() ok ! \n");
}
if (listen(m_socket, 1) == SOCKET_ERROR) {
printf("Listen() failed ! %d\n ", WSAGetLastError());
} else {
printf("Listen() ok ! \n");
}
SOCKET AcceptSocket;
printf("waiting for Client...\n \n");
int addresslen = sizeof(service);
while (AcceptSocket = accept(m_socket, (sockaddr*)&service, &addresslen)) {
printf("Server dan Client connected --> ");
char *ClientIP = inet_ntoa(service.sin_addr);
int ClientPort = ntohs(service.sin_port);
printf("IP: %s:%d\n ", ClientIP, ClientPort);
char *Filesize = new char[10];
int Size = 0;
int recv_size, recv_file;
char Buffer[MAXCHAR];
FILE *File;
recv_file = recv(AcceptSocket, Buffer, Size, 0);
recv_size = recv(AcceptSocket, Filesize, 10, 0);
while (Filesize) {
//Menerima File Size
Size = atoi((const char*)Filesize);
File = fopen("D:\\fileReceived.txt", "wb");
fwrite((const char*)Buffer, 1, Size, File);
fclose(File);
printf("File received \n");
ZeroMemory(Buffer, Size);
// printf("File size : %d\n",Size);
recv_file = recv(AcceptSocket, Buffer, Size, 0);
recv_size = recv(AcceptSocket, Filesize, 10, 0);
}
}
}
Client Code
// client.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <winsock2.h>
#include <Windows.h>
#include <stdio.h>
using namespace std;
int Size = 0;
char *Buffer;
int _tmain(int argc, _TCHAR* argv[])
{
WORD wVersionRequested;
WSADATA wsaData;
int wsaerr;
wVersionRequested = MAKEWORD(2, 2);
wsaerr = WSAStartup(wVersionRequested, &wsaData);
if (wsaerr != 0) {
printf("The Winsock DLL not found \n ");
} else {
printf("The Winsock DLL found \n ");
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("not support Winsock version 2.2 ");
} else {
printf("support winsock version 2.2 \n ");
}
SOCKET Client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (Client_socket == INVALID_SOCKET) {
printf("Error di socket(): %ld\n", WSAGetLastError());
WSACleanup();
} else{
printf("Socket() ok ! \n");
}
SOCKADDR_IN clientService;
clientService.sin_family = AF_INET;
clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
clientService.sin_port = htons(55555);
if (connect(Client_socket, (SOCKADDR*)&clientService, sizeof(clientService)) == SOCKET_ERROR) {
printf("connect() fail ! \n");
} else {
printf(" connect() ok .... \n ");
while (1){
FILE *File;
File = fopen("D:\\logging21.txt", "rb");
if (!File){
printf("", WSAGetLastError());
}
printf("File open ok ! \n");
fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);
char cisi[10];
sprintf(cisi, "%i", Size);
// fclose(File);
send(Client_socket, cisi, 10, 0); //file size sent
// Sleep(6000);
Buffer = (char*)malloc(Size + 1);
fread(Buffer, Size, 1, File);
fclose(File);
send(Client_socket, Buffer, Size, 0); // File Binary sent
free(Buffer);
printf("sending finished....\n");
Sleep(6000);
}
}
}
The server is riddled with errors, but this is the most relevant to the asked question: Why can I only send a few bytes?
char *Filesize = new char[10];
int Size = 0; // note the size is set to zero
int recv_size, recv_file;
char Buffer[MAXCHAR];
// no idea how big MAXCHAR is, but it turns out to be irrelevant
FILE *File;
recv_file = recv(AcceptSocket, Buffer, Size, 0);
// Above we use that size of zero to read zero bytes from the socket
recv_size = recv(AcceptSocket, Filesize, 10, 0);
// get the size of the file. This doesn't seem too bad
while (Filesize) { // but we just used a 10 byte blob of data containing who knows what
// as the exit condition from a while loop.
// never use anything from an external source, especially the internet
// without validating and verifying first.
//Menerima File Size
Size = atoi((const char*)Filesize); // atoi fails to convert silently. Use strtol instead.
File = fopen("D:\\fileReceived.txt", "wb"); // open file
fwrite((const char*)Buffer, 1, Size, File);
// write over file contents with what we hope is filesize from a buffer into
// which we read zero bytes. File now full of random crap.
fclose(File);
printf("File received \n");
ZeroMemory(Buffer, Size);
// printf("File size : %d\n",Size);
recv_file = recv(AcceptSocket, Buffer, Size, 0);
// read size of the **last file** (we hope) into buffer
recv_size = recv(AcceptSocket, Filesize, 10, 0);
}
At the very least, filesize must be read before trying to read the file.
Important fun fact about TCP: TCP is a stream, not a packet. Do not assume that because you wrote a number with send that the number is the only thing waiting to be read. For efficiency, TCP packs data together, so if you send "1234" and then a file 1234 bytes long, odds are pretty good both the file size and the file will arrive at the same time. So recv of 10 bytes will very likely read 1234, "1234"'s terminating null, and the first five bytes of the file. It's now up to you to separate the file length from the file data.
But if you send the length as a 32 bit integer, it will always be 4 bytes. Easy, yes? No. Because some computers and network protocols represent numbers backwards. I'm serious here. Google up endian.
Next: recv returns the number of bytes read. You may not get the number of bytes you asked for and have to keep asking until you get the while thing. recv also returns -1 if something goes wrong, so every time you recv, check that the return code is positive and that it's the number of bytes you need before doing anything with the data. Reading a 32 bit filesize, getting only 24 bits, and then trying to use those 24 bits to do meaningful work will really ruin your day.
And there's more! What if MAXCHARS is smaller than the size of the file? Well, that one is easy. You recv MAXCHARS or the number of bytes left in the file and write it out until the file is done.
So:
recv file size
Make sure it's really the filesize and nothing else.
open the output file
while file size is greater than zero
recv up to MAXCHARS or file size, whichever is lower, into buffer
if the number of bytes read is greater than zero
write the number of bytes read from buffer into output file
subtract the number of bytes read from file size
else
something bad happened to the connection. Give up.
close file
You tagged your question as C++ but the code is pretty much entirely C.
Here is a somewhat more C++ version of the server code. To finish the project, your client will need to start by sending a populated "FileTransfer" object, e.g.
FileTransfer xfer(file.size);
auto result = send(send_socket, &xfer, sizeof(xfer), 0);
then send the data from the file, ideally read <= FileTransfer::BufferSize bytes and then push them onto the socket until you have reach all the bytes you promised to send.
// move the code between 8x----x8x into protocol.h
// 8x---- snip ----x8
#pragma once
// protocol.h
#ifndef PROTOCOL_H
#define PROTOCOL_H 1
#include <cstdint>
struct FileTransfer
{
enum { ProtoVersion = 1 };
static const size_t BufferSize = 4 * 4096;
uint32_t m_proto;
size_t m_size;
FileTransfer(size_t size_) : m_proto(ProtoVersion), m_size(size_) {}
FileTransfer() : m_proto(0), m_size(0) {}
};
#endif // PROTOCOL_H
// 8x---- snip ----x8
// server.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#define NOMINMAX
#include <WinSock2.h>
#include <Windows.h>
#include <Ws2tcpip.h>
#include <algorithm>
#include <fstream>
#include <iostream>
//#include "protocol.h"
#pragma comment(lib, "Ws2_32.lib")
void _describeConnection(sockaddr_in& service)
{
char clientIP[128];
inet_ntop(AF_INET, &(service.sin_addr), clientIP, sizeof(clientIP));
auto clientPort = ntohs(service.sin_port);
std::cout << "new connection from " << clientIP << ':' << clientPort << "\n";
}
bool _errorIndicatesInterrupted()
{
auto err = WSAGetLastError();
return (err == WSAEINTR || err == WSAEINPROGRESS);
}
void _receiveFile(SOCKET socket)
{
FileTransfer xfer;
auto recv_size = recv(socket, reinterpret_cast<char*>(&xfer), sizeof(xfer), 0);
if (recv_size < sizeof(xfer)) {
std::cout << "error: only " << recv_size
<< " bytes while recv()ing FileTransfer\n";
return;
}
if (xfer.m_proto != FileTransfer::ProtoVersion) {
std::cout << "error: connection protocol " << xfer.m_proto
<< " not supported\n";
return;
}
if (xfer.m_size <= 0) {
std::cout << "error: zero length transfer\n";
return;
}
std::ofstream out("D:\\fileReceived.txt", std::ios::binary | std::ios::trunc);
char recvBuffer[FileTransfer::BufferSize];
size_t bytesLeft = xfer.m_size;
while (bytesLeft) {
do {
recv_size = recv(socket, recvBuffer, std::min(bytesLeft, FileTransfer::BufferSize), 0);
} while (recv_size < 0 && _errorIndicatesInterrupted());
if (recv_size < 0) {
std::cout << "error: transfer aborted\n";
return;
}
out.write(recvBuffer, recv_size);
bytesLeft -= recv_size;
}
std::cout << "transfered " << xfer.m_size << " bytes\n";
}
bool _server()
{
SOCKET m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == INVALID_SOCKET) {
std::cout << "socket() failed! " << WSAGetLastError() << "\n";
return false;
}
sockaddr_in service;
service.sin_family = AF_INET;
inet_pton(service.sin_family, "127.0.0.1", &service.sin_addr.s_addr);
service.sin_port = htons(55555);
int m_bind = bind(m_socket, (sockaddr*)&service, sizeof(service));
if (m_bind == SOCKET_ERROR) {
std::cout << "bind() failed! " << WSAGetLastError() << "\n";
return false;
}
if (listen(m_socket, 1) == SOCKET_ERROR) {
std::cout << "listen() failed! " << WSAGetLastError() << "\n";
return false;
}
// This code can only accept one connection at a time.
int addresslen = sizeof(service);
for (;;) {
std::cout << "waiting for client...\n";
SOCKET acceptSocket = accept(m_socket, (sockaddr*)&service, &addresslen);
if (acceptSocket < 0) {
std::cout << "accept() failed: " << WSAGetLastError() << "\n";
return false;
}
_describeConnection(service);
_receiveFile(acceptSocket);
closesocket(acceptSocket);
}
}
int _tmain()
{
WSADATA wsaData;
WORD wVersionRequested = MAKEWORD(2, 2);
int wsaerr = WSAStartup(wVersionRequested, &wsaData);
if (wsaerr != 0) {
std::cout << "WinSock DLL not found\n";
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
std::cout << "WinSock 2.2 required\n";
return 1;
}
_server();
// system("PAUSE"); Just use CTRL+F5.
return 0;
}
If this is not a homework project and you are earnestly trying to get a file transfer project set up, consider using one of the libraries mentioned here: Best C/C++ Network Library.
I made a server and client that should transfer files.
I tried to make it read the whole file and send it.
But now as I see it, I am having a problem.
Server should automatically send the file when the client is connected.
But the file is empty, and I don't know where the problem is
You can see that I'm trying to send .txt file. But I would like in the future send a big file, but not bigger than 1MB.)
Edit:
Picture here: http://img819.imageshack.us/img819/8259/aadi.jpg
Left side: The file that I tried to send.
Right side: The file I received
The Problem: The file that I received has been damaged, and I can't use it.
Server:
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
#define Port 6000
SOCKET Socket, Sub;
WSADATA Winsock;
sockaddr_in Addr;
sockaddr_in IncomingAddress;
int AddressLen = sizeof(IncomingAddress);
int main()
{
WSAStartup(MAKEWORD(2, 2), &Winsock); // Start Winsock
if(LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) // Check version
{
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&Addr, sizeof(Addr));
Addr.sin_family = AF_INET;
Addr.sin_port = htons(Port);
bind(Socket, (sockaddr*)&Addr, sizeof(Addr));
if(listen(Socket, 1) == SOCKET_ERROR)
{
printf("listening error\n");
}
else
{
printf("listening ok\n");
}
if(Sub = accept(Socket, (sockaddr*)&IncomingAddress, &AddressLen))
{
char *ClientIP = inet_ntoa(IncomingAddress.sin_addr);
int ClientPort = ntohs(IncomingAddress.sin_port);
printf("Client conncted!\n");
printf("IP: %s:%d\n", ClientIP, ClientPort);
printf("Sending file .. \n");
FILE *File;
char *Buffer;
unsigned long Size;
File = fopen("C:\\Prog.rar", "rb");
if(!File)
{
printf("Error while readaing the file\n");
getchar();
return 0;
}
fseek(File, 0, SEEK_END);
Size = ftell(File);
fseek(File, 0, SEEK_SET);
Buffer = new char[Size];
fread(Buffer, Size, 1, File);
char cSize[MAX_PATH];
sprintf(cSize, "%i", Size);
fclose(File);
send(Sub, cSize, MAX_PATH, 0); // File size
//int len = Size;
//char *data = Buffer;
int Offset = 0;
while(Size > Offset)
{
int Amount = send(Sub, Buffer + Offset, Size - Offset, 0);
if(Amount <= 0)
{
cout << "Error: " << WSAGetLastError() << endl;
break;
}
else
{
Offset += Amount;
printf("2\n");
}
}
free(Buffer);
closesocket(Sub);
closesocket(Socket);
WSACleanup();
}
getchar();
return 0;
}
Client:
#include <WinSock2.h>
#include <Windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
SOCKET Socket;
WSADATA Winsock;
sockaddr_in Addr;
int Addrlen = sizeof(Addr);
int main()
{
WSAStartup(MAKEWORD(2, 2), &Winsock); // Start Winsock
if(LOBYTE(Winsock.wVersion) != 2 || HIBYTE(Winsock.wVersion) != 2) // Check version
{
WSACleanup();
return 0;
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ZeroMemory(&Addr, sizeof(Addr)); // clear the struct
Addr.sin_family = AF_INET; // set the address family
Addr.sin_addr.s_addr = inet_addr("127.0.0.1");
Addr.sin_port = htons(6000); // set the port
if(connect(Socket, (sockaddr*)&Addr, sizeof(Addr)) < 0)
{
printf("Connection failed !\n");
getchar();
return 0;
}
printf("Connection successful !\n");
printf("Receiving file .. \n");
int Size;
char *Filesize = new char[1024];
if(recv(Socket, Filesize, 1024, 0)) // File size
{
Size = atoi((const char*)Filesize);
printf("File size: %d\n", Size);
}
char *Buffer = new char[Size];
//int len = Size;
//char *data = Buffer;
int Offset = 0;
while(Size > Offset)
{
int Amount = recv(Socket, Buffer + Offset, Size - Offset, 0);
if(Amount <= 0)
{
cout << "Error: " << WSAGetLastError() << endl;
break;
}
else
{
Offset += Amount;
printf("2\n");
}
}
FILE *File;
File = fopen("Prog.rar", "wb");
fwrite(Buffer, 1, Size, File);
fclose(File);
getchar();
closesocket(Socket);
WSACleanup();
return 0;
}
The send API may not send all the data you requested to send. So, you have to pay attention to the return value, and retry the send from where the last send ended. As an example:
offset = 0;
while (offset < bufsize) {
r = send(socket, buf+offset, bufsize-offset);
if (r <= 0) break;
offset += r;
}
While you are doing something similar for your file transfer, you do not make sure this is the case for your file size.
When you send the file size, you only need to send the string that represents the size, not the entire MAX_PATH. The receiver then needs to parse the first string to determine the size, but any data read in after the end of the first string needs to be considered part of the file. However, since you are trying the send MAX_PATH, the receiver should receive the same amount. Your client code receives 1024 bytes, but there is no indication this is the same size as MAX_PATH.
The recv API may also return fewer bytes than requested. You use a loop to handle reading the file, but you may need a loop to read the entire message that contains the file size.
In your client receive loop, you are incrementing the data pointer. This makes it unusable to write out the file later. You already have Buffer though, so use that to write out your file.
fwrite(Buffer, 1, len, File);
If you encounter an error doing socket I/O, you can retrieve the error with WSAGetLastError(), or you can issue getsockopt() on the socket with the SO_ERROR option. These may return different values, but the error reason should be correlated.
Myself faced the same problem and after googling found that send() api can send a maximum data based on low level TCP buffers which are os dependent.So inorder to send a huge file we need to perform file chunking , ie send the file in the form of chunks.
`const int FILE_CHUNK_SIZE = 2000;
//get file size
ifstream file("myFile.file", ios::binary);
file.seekg(0, ios::end);
unsigned int fileSize = file.tellg();
file.close();
//get the file
char* fileBuffer = new char[fileSize];
file.open("myFile.file", ios::binary);
file.seekg (0, ios::beg);
file.read (fileBuffer, fileSize);
file.close();
//send file in chunks
unsigned int bytesSent = 0;
int bytesToSend = 0;
while(bytesSent < fileSize)
{
if(fileSize - bytesSent >= FILE_CHUNK_SIZE)
bytesToSend = FILE_CHUNK_SIZE;
else
bytesToSend = fileSize - bytesSent;
send(ConnectSocket, fileBuffer + bytesSent, bytesToSend, 0 );
bytesSent += bytesToSend;
}
delete [] fileBuffer;`
At the receiving end we need to have a recv() api called till the whole file content is read.
credits to:shacktar cplusplus.com
I'm new to socket programming and I have this client that tries to connect to a server on the same computer. But the server hangs there after bind or accept—cause bind seems to be right but no output. I know that the server works because another client can connect just fine and the client seems to have done that. What causes the server to not see this incoming connection? I'm at the end of my wits here.
And I haven't been used to programming on Mac, so thank you so much for your patience if I have made some foolish mistakes.
My code is as follows:
server.cpp
using namespace std;
#include<iostream>
#include <netinet/in.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#define PORT 8888
#define BACKLOG 20
//#define DEST_IP "127.0.0.1"
int process_conn_server(int s)
{
ssize_t size =0;
char buffer[1024];
for( ; ; )
{
size = read(s,buffer,1024);
if(size == 0)
{
return 0;
}
}
sprintf(buffer, "%d bytes altogether\n", (int)size);
write(s, buffer,strlen(buffer)+1);
return 0;
}
int main(int argc,char *argv[])
{
//cout<<"?";
int ss, sc, r, err;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int opt=1;
pid_t pid;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(PORT);
ss = socket(AF_INET, SOCK_STREAM, 0);
if(ss<0)
{
cout<<"[process infro]socket error"<<endl;
return -1;
}
cout<<"[process infro]socket successful"<<endl;
r = setsockopt(ss, SOL_SOCKET,SO_REUSEADDR, (void*)&opt,sizeof(opt));
if (r == -1)
{
perror("setsockopt(listen)");
return 0;
}
cout<<"[process infro]sockopt successful"<<endl;
cout<<"?";
err = bind(ss, (struct sockaddr*) &server_addr, sizeof( server_addr));
cout<<"err";
if(err < 0)
{
cout<<"[process infro]bind error"<<endl;
return -1;
}
cout<<"[process infro]bind successful";
err=listen(ss, BACKLOG);
if(err <0)
{
cout<<"[process infro]listen error"<<endl;
return -1;
}
cout<<"[process infro]lisen successful";
for( ; ; )
{
int addrlen = sizeof(struct sockaddr);
sc = accept(ss, (struct sockaddr*)&client_addr, (socklen_t *)&addrlen);
if(sc < 0)
{
continue;
}
pid = fork();
if (pid == 0)
{
close(ss);
process_conn_server(sc);
}
else
{
close(sc);
}
}
//opt=0;
//setsockopt(ss,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(len));
}
client.cpp
using namespace std;
#include<iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <time.h>
#include <arpa/inet.h>
#include <fstream.h>
#define PORT 8888
#define DEST_IP "127.0.0.1"
void process_conn_client(int s)
{
ssize_t size = 0;
char buffer[1024];
//read from the file to be sent
fstream outfile("programm.txt",ios::in|ios::out);
if (outfile.fail())
{
printf("[process infro]cannot open the file to be sent\n");
return ;
}
printf("[process infro]successfully open the file to be sent\n");
while(!outfile.eof())
{
outfile.getline(buffer,1025,'\n');
write(s,buffer,1024);
size = read(s, buffer, 1024);
if(size = 0)
{
return ;
}
//write to the server
write(s,buffer,size);
//get response from the server
size=read(s,buffer,1024);
write(1,buffer,size);
}
outfile.close(); //关闭文件
}
int main(int argc,char *argv[])
{
int s;
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(DEST_IP);
server_addr.sin_port = htons(PORT);
s = socket(AF_INET, SOCK_STREAM, 0);
if(s < 0)
{
cout<<"[process infro]socke error"<<endl;
return -1;
}
cout<<"[process infro] socket built successfully\n";
//inet_pton(AF_INET, argv[1], &server_addr.sin_addr);
connect(s, (struct sockaddr*)&server_addr, sizeof(struct sockaddr));
cout<<"[process infor] connected\n";
process_conn_client(s);
close(s);
return 0;
}
This may be unrelated.... but it won't fit in a comment...
In your server you do this:
int process_conn_server(int s)
{
ssize_t size =0;
char buffer[1024];
for( ; ; )
{
// keep reading until read returns 0
size = read(s,buffer,1024);
if(size == 0)
{
return 0;
}
}
sprintf(buffer, "%d bytes altogether\n", (int)size);
write(s, buffer,strlen(buffer)+1);
return 0;
}
In your client you do this:
void process_conn_client(int s)
{
ssize_t size = 0;
char buffer[1024];
//read from the file to be sent
fstream outfile("programm.txt",ios::in|ios::out);
if (outfile.fail())
{
printf("[process infro]cannot open the file to be sent\n");
return ;
}
printf("[process infro]successfully open the file to be sent\n");
while(!outfile.eof())
{
outfile.getline(buffer,1025,'\n');
// write to server?
write(s,buffer,1024);
// read from server?
size = read(s, buffer, 1024);
if(size = 0)
{
return ;
}
//write to the server
write(s,buffer,size);
//get response from the server
size=read(s,buffer,1024);
write(1,buffer,size);
}
outfile.close();
}
It's a bit hard to follow because of your variable names, but it looks like your client is working under the assumption that your server will send back a response for every chunk of data received, which isn't the case. You server doesn't appear to have changed the accepted socket to non-blocking, so it's going to block on the read call until there is some data to read (it's never going to get 0)...
Are you sure it's failing before this point? Do you have some sample output?
Aso, in your call to accept, you pass addrlen...
int addrlen = sizeof(struct sockaddr);
I think this should be:
int addrlen = sizeof(struct sockaddr_in); /* sizeof(client_addr) */
sending and recieving file from tcp socket. Sending the file works however trying to save the file does not work.
#include <cassert>
#include <arpa/inet.h>
#include <cstdlib>
#include <iostream>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <fstream>
#include <time.h>
#include <strings.h>
#include <sstream>
#include <vector>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/sendfile.h>
#include <fcntl.h>
using namespace std;
using std::endl;
int newscount = 0;
int doccount = 0;
int photocount = 0;
int johns = 0;
vector<string> newsvector;
vector<string> photosvector;
vector<string> docsvector;
void serverlogs(const char*msg) /* writing to log file */
{
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime(&rawtime);
ofstream file;
file.open("serverlog.txt",ios::app);
if (file.is_open())
{file<<msg;
file<<" # ";
file<<asctime(timeinfo);
file<<"\n";
file.close();
return;
}
else
cout<<"Error Creating log file";
return;
}
void clientlogs(const char*msg) /* writing to log file */
{
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime(&rawtime);
ofstream file;
file.open("clientlog.txt",ios::app);
if (file.is_open())
{file<<msg;
file<<" # ";
file<<asctime(timeinfo);
file<<"\n";
file.close();
return;
}
else
cout<<"Error Creating log file";
return;
}
void error(const char*msg) /* If there is an error exit the program with err# 1 */
{
perror(msg);
exit(1);
}
void publishdocsvector(const char*msg)
{
docsvector.push_back(msg);
ofstream file;
file.open("docfiles.txt",ios::app);
if (file.is_open())
{
for(int j = 0; j < docsvector.size() ;j++)
{file<<docsvector[j];}
file.close();
}
else
cout<<"Error creating news archive";
return;
}
void publishphotosvector(const char*msg)
{
photosvector.push_back(msg);
ofstream file;
file.open("photofiles.txt",ios::app);
if (file.is_open())
{
for(int j = 0; j < photosvector.size() ;j++)
{file<<photosvector[j];}
file.close();
}
else
cout<<"Error creating news archive";
return;
}
void publishnewsvector(const char*msg)
{
newsvector.push_back(msg);
ofstream file;
file.open("newsfiles.txt",ios::app);
if (file.is_open())
{
for(int j = 0; j < newsvector.size() ;j++)
{file<<newsvector[j];}
file.close();
}
else
cout<<"Error creating news archive";
return;
}
void sendfile(const char*msg)
{
// to be implemented later//
}
int main (int argc, char*argv[]) /*Main Program accepting a port number and something else for arguments */
{
int sockfd, newsockfd, portno, clilen, n,test;
string publish="publish";
string search= "search";
string get="get";
string newsstring = "news";
string docstring = "doc";
string photostring = "photo";
string wrap = "exit";
char buffer[256];
char seats [50];
serverlogs("Server Running");
struct sockaddr_in serv_addr, cli_addr; /* Defines the server address and client address and types of structures with the same format as socket address */
if (argc < 2)
{
fprintf(stderr,"Please provide a port number next time plz, goodbye!");
exit(1);
}
sockfd = socket(AF_INET, SOCK_STREAM, 0); /* If Sock_Dgram then then it will open a udp socket */
if (sockfd < 0)
error("Error opening socket");
bzero((char *)&serv_addr, sizeof(serv_addr)); /* sets the server address to zero usings its reference */
portno = atoi(argv[1]); /*2nd argument vector is the port number and converted into an integer, the first [0] is the running program */
serv_addr.sin_family = AF_INET; /* The structure sockaddr_in has four fields, this is first one and should always be this */
serv_addr.sin_port = htons(portno); /* convert port number into network byte order */
serv_addr.sin_addr.s_addr = INADDR_ANY; /*3rd Field uses Ip address of host machine */
if (bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr))<0) /*bind socket to sockfd and address of server ,and needs size of address need struct of sockaddr, see bind man for details*/
error("Couldn't bind socket to address");
listen(sockfd,5);
clilen = sizeof(cli_addr);
serverlogs("going into server loop");
int pid = fork();
if (pid < 0)
serverlogs("error on initial separtion of server and client");
if (pid==0)
{
// server loop later on this will be the child process and client will be main
while (1)
{ /* Server loop loop*/
newsockfd = accept(sockfd,(struct sockaddr *) &cli_addr, (socklen_t*)&clilen);
if (newsockfd < 0)
/* error("Corrupt log"); */
serverlogs("Connection not accepted");
else (newsockfd > 0);
int ppID = fork();
if (ppID < 0)
serverlogs("A new server process failed to be created");
if (ppID == 0)
{
int uid;
uid = johns;
printf("A new client connected with identity: %d\n", getpid());
close(sockfd);
serverlogs("A john Connected to the server");
printf("my unique id: %d\n", uid);
serverlogs(seats);
bzero(buffer,256);
//n = write(newsockfd,"Each client is a 'john' \n",26);
/* This loop read from socket and writes to other persons sockets */
while(1)
{
bzero(buffer,256);
n = read(newsockfd,buffer,256);
if (n < 0)
printf ("error reading from socket here is the message: %s",buffer);
if (publish[0] == buffer[0])
{
n = write(newsockfd,"What category are you publishing in?(news,photos,documents) \n",62);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
if(buffer[0]==newsstring[0])
{
n = write(newsockfd,"Type the name of the file to publish and wait 10 seconds \n",59);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
publishnewsvector(buffer);
serverlogs(seats);
serverlogs("client is trying to publish a news file:");
serverlogs(buffer);
/*start recieving a file*/
std::ofstream file;
file.open(buffer, std::ios::out | std::ios::binary);
assert(file.is_open());
while (1) {
std::cout << "..";
bzero(buffer,256);
n = read(newsockfd, buffer, sizeof(buffer));
assert(n != -1);
if (n == 0)
break;
file.write(buffer, n);
i++;
}
file.close();
serverlogs("File Transfered successfully");
}
if(buffer[0]==docstring[0])
{
n = write(newsockfd,"Type the name of the file to publish \n",39);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
publishdocsvector(buffer);
serverlogs(seats);
serverlogs("client is tyring to publish a document:" );
serverlogs(buffer);
/*start recieving a file*/
std::ofstream file;
file.open(buffer, std::ios::out | std::ios::binary);
assert(file.is_open());
while (1) {
std::cout << ".";
bzero(buffer,256);
n = read(newsockfd, buffer, sizeof(buffer));
assert(n != -1);
if (n == 0)
break;
file.write(buffer, n);
}
file.close();
serverlogs("File Transfered successfully");
}
if(buffer[0]==photostring[0])
{
n = write(newsockfd,"Type the name of the file to publish \n",39);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
publishphotosvector(buffer);
serverlogs(seats);
serverlogs("client is trying to publish photo file:" );
serverlogs(buffer);
/*start recieving a file*/
std::ofstream file;
file.open(buffer, std::ios::out | std::ios::binary);
assert(file.is_open());
while (1) {
std::cout << ".";
bzero(buffer,256);
n = read(newsockfd, buffer, sizeof(buffer));
assert(n != -1);
if (n == 0)
break;
file.write(buffer, n);
}
file.close();
serverlogs("File Transfered successfully");
}
}
if (get[0] ==buffer[0])
{
n = write(newsockfd,"\n What file do you want to get? \n",35);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
serverlogs(seats);
serverlogs("client wants file:");
serverlogs(buffer);
//** start sending the file**//
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen(buffer,"r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
serverlogs("Sent the file to the client");
serverlogs(seats);
}
if (search[0] == buffer[0])
{
bzero(buffer,256);
n = write(newsockfd,"What category are you searching? \n",35);
bzero(buffer,256);
n = read(newsockfd,buffer,256);
serverlogs(seats);
serverlogs("client searching for");
serverlogs(buffer);
if(buffer[0]==newsstring[0])
{
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen("newsfiles.txt","r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
}
if(buffer[0]==docstring[0])
{
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen("docfiles.txt","r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
}
if(buffer[0]==photostring[0])
{
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen("photofiles.txt","r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
n = write(newsockfd,bufferfile,256);
fclose(searchfile);
}
}
if(buffer[0]==wrap[0])
{
close(sockfd);
close(newsockfd);
johns = johns - 1;
serverlogs("A john left");
return 0;
}
n = write(newsockfd,"\n Waiting for a command I can understand:(publish,search,get,exit)",66);
} /* while loop to listen to commands from client bracket */
}/*what to do when client connected*/
} /*Creating child/zombies */
} /* division between client and server*/
else
{
while (1)
{int ssockfd, pportno, p,peer;
struct sockaddr_in peer_addr;
struct hostent *peerserver;
char bbuffer[256];
printf ("%s \n", "Welcome to the Social");
printf ("%s \n", "Please type the port number of the server \n");
cin>>pportno;
ssockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening socket Please try again");
printf ("%s \n", "Please type in the hostname of client ie sunlab1.njit.edu \n");
char peers[256];
cin >> peers;
peerserver = gethostbyname(peers);
if (peerserver == NULL)
{
fprintf(stderr,"could not connect to ip address");
peerserver = gethostbyname((const char*)peer);
if (peerserver == NULL)
fprintf(stderr,"still null");
exit(0);
}
bzero((char *) &peer_addr, sizeof(peer_addr));
peer_addr.sin_family = AF_INET;
bcopy((char *)peerserver->h_addr,(char *)&peer_addr.sin_addr.s_addr,peerserver->h_length);
peer_addr.sin_port = htons(pportno);
if (connect(ssockfd,(struct sockaddr *)&peer_addr,sizeof(peer_addr)) < 0)
error("ERROR connecting");
clientlogs("Connected to peer");
clientlogs((const char*)&peer);
printf("Please enter a command, publish,search or get: ");
while (1)
{
bzero(bbuffer,256);
fgets(bbuffer,255,stdin);
char apub[] = "publish";
char asearch[] = "search";
char aget[]="get";
if (bbuffer[0]==apub[0] && bbuffer[1]==apub[1])
{
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //What category are you publishing in//
bzero(bbuffer,256);
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
clientlogs("Client publishing");
clientlogs(bbuffer);
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //Type the name of the file//
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
clientlogs(bbuffer);
FILE* searchfile = 0;
long Size = 0;
searchfile = fopen(bbuffer,"r");
fseek(searchfile, 0, SEEK_END);
Size = ftell(searchfile);
char *bufferfile = (char*)malloc(Size);
memset(bufferfile, 0, Size);
fseek(searchfile, 0, SEEK_SET);
fread(bufferfile, Size, 1, searchfile);
p = write(ssockfd,bufferfile,256);
fclose(searchfile);
}
if(bbuffer[0]==aget[0] && bbuffer[1]==aget[1])
{
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //What file do you want to get? //
bzero(bbuffer,256);
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
clientlogs("client wants file:");
clientlogs(bbuffer);
/*start recieving a file*/
std::ofstream file;
file.open(bbuffer, std::ios::out | std::ios::binary);
assert(file.is_open());
char buffer[255];
while (1) {
std::cout << ".";
bzero(bbuffer,256);
p = read(ssockfd, bbuffer, sizeof(bbuffer));
assert(p != -1);
if (p == 0)
break;
file.write(bbuffer, p);
}
file.close();
serverlogs("File Transfered successfully");
}
if (bbuffer[0]==asearch[0] && bbuffer[1]==asearch[1])
{
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); // what category? //
fgets(bbuffer,255,stdin);
p = write(ssockfd,bbuffer,strlen(bbuffer));
if (p < 0)
error("ERROR writing to socket");
clientlogs("Client searching for file");
clientlogs(bbuffer);
bzero(bbuffer,256);
p = read(ssockfd,bbuffer,255);
if (p < 0)
error("ERROR reading from socket");
printf("%s",bbuffer); //The vector array of the files //
}
if (bbuffer[0]==wrap[0] && bbuffer[1]==wrap[1])
{ p = write(ssockfd,bbuffer,strlen(bbuffer));
exit(0); }
}//end of client loop asking to enter a command
}
}
return 0;
}
The problem I see is file << bbuffer. The ofstream's << operator writes until the first NULL byte. Don't forget your buffer is a string (or better, a char *). So, if bbuffer doesn't contain a NULL byte, your program is likely to crash with a SIGSEGV.
You should use file.write(bbuffer, p) instead of file << bbuffer. Also, there's no need to cleanup your buffer using bzero or memset.
And since you didn't provide a compilable source, I wrote the following (supposing Linux/Unix):
#include <cassert>
#include <iostream>
#include <fstream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main() {
int fd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sa_dst;
memset(&sa_dst, 0, sizeof(struct sockaddr_in));
sa_dst.sin_family = AF_INET;
sa_dst.sin_port = htons(1234);
sa_dst.sin_addr.s_addr = inet_addr("127.0.0.1");
int ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr));
assert(ret != -1);
std::ofstream file;
file.open("received.bin", std::ios::out | std::ios::binary);
assert(file.is_open());
char buffer[255];
while (1) {
std::cout << "..";
ssize_t p = read(fd, buffer, sizeof(buffer));
assert(p != -1);
if (p == 0)
break;
file.write(buffer, p);
}
file.close();
}
You can test it using netcat on your terminal:
$ nc -l 1234 < some_binary_file &
$ ./program
$ cmp some_binary_file received.bin