When I send a file using C++ Socket, random bytes are added at the beginning. The problem occurs every few attemps. I tried to clear the buffers using different ways but nothing worked so far. I also noticed that in the received file i can see strings such as "File Size is".
I m using 2 Docker containers, each runs Ubuntu 20.04 LTS.
This is the code i use to send the files:
int Socket::send_file(string path,int socket_){
if (socket_ == -1 )
{
socket_ = clientSd ;
}
ifstream fichier ;
fichier.open(path,ios::in | ios::binary);
if (fichier.is_open())
{
cout << "File Opened " << endl ;
}else
{
cout << "Failed to open file " << endl ;
exit(0);
}
int size = get_file_size(fichier);
fichier.close();
char msg[MAX_BUFFER];
sprintf(msg, "%d\0", size);
cout << "File Size is " << size << endl ;
send(socket_, (char*)msg, sizeof(msg) , 0); // 2
char buffer[MAX_BUFFER]; // 4222111
const char *c = path.c_str();
sprintf(buffer, "%d\0", size);
FILE *fd = fopen(c, "rb");
size_t rret, wret;
int bytes_read;
int fragment = MAX_BUFFER ;
while (!feof(fd)) {
if ((bytes_read = fread(&buffer, 1, MAX_BUFFER, fd)) > 0)
send(socket_, buffer, bytes_read, 0);
else
break;
}
fclose(fd);
cout << "End" << endl ;
return 1 ;
}
This is the code i use to receive the files:
int Socket::receive_file(string path,int socket_){
if (socket_ == -1 )
{
socket_ = clientSd ;
}
char* buffer ;
buffer = (char*) malloc(sizeof(char) * MAX_BUFFER) ;
recv(socket_, (char*)buffer, MAX_BUFFER, 0); // 3
int size = atoi(buffer) ;
cout << "File Size is " << size << endl ;
size_t datasize;
char text[MAX_BUFFER]; // 1024
const char *c = path.c_str();
FILE* fd = fopen(c, "wb");
int received = 0 ;
while (received < size)
{
datasize = recv(socket_, text, sizeof(text), 0);
fwrite(&text, 1, datasize, fd);
}
fclose(fd);
cout << "End" << endl ;
return 1 ;
}
Related
I am trying to learn OPENSSL and following this tutorial. I have written following code to read from a file and write the encoded form in another file.
#include <iostream>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#define MAX_BUFFER_SIZE 512
int main (int argc, char* argv[])
{
BIO* bio_out = nullptr;
BIO* bio_in = nullptr;
BIO* bio_b64 = nullptr;
int in_byte, out_byte;
char buffer[MAX_BUFFER_SIZE];
std::memset(buffer, '\0', MAX_BUFFER_SIZE);
if (argc != 3)
{
std::cout << "Usage: bio_b64_encode <source-read> <encoded-write>\n";
return 1;
}
bio_in = BIO_new_file(argv[1], "r");
bio_out = BIO_new_file(argv[2], "wb");
bio_b64 = BIO_new(BIO_f_base64());
BIO_push(bio_b64, bio_out);
in_byte = BIO_read(bio_in, buffer, MAX_BUFFER_SIZE);
while (in_byte > 0)
{
std::cout << "Read " << in_byte << " bytes.\n";
out_byte = BIO_write(bio_b64, buffer, in_byte);
std::cout << "Wrote " << out_byte << " bytes.\n";
if (in_byte != out_byte)
{
std::cout << "In bytes: " << in_byte << "and Out bytes: " << out_byte << " are not equal.\n";
BIO_free(bio_in);
BIO_free(bio_out);
return 1;
}
in_byte = BIO_read(bio_in, buffer, MAX_BUFFER_SIZE);
}
BIO_free(bio_in);
BIO_free_all(bio_b64);
return 0;
}
The code reads properly from the input file given in argv[1] and tries to write to argv[2] but when I open the output file, it is empty but it should have the encoded text from the input file.
the output of the above program when I run ./bio_b64_encode in.txt out.txt is
Read 22 bytes.
Wrote 22 bytes.
but the output file is empty. If I remove the encoding constraints and try to simply write whatever I read from input file (the code is below), it works properly.
#include <iostream>
#include <openssl/ssl.h>
#include <openssl/bio.h>
#define MAX_BUFFER_SIZE 512
int main (int argc, char* argv[])
{
BIO* bio_out = nullptr;
BIO* bio_in = nullptr;
BIO* bio_b64 = nullptr;
int in_byte, out_byte;
char buffer[MAX_BUFFER_SIZE];
std::memset(buffer, '\0', MAX_BUFFER_SIZE);
if (argc != 3)
{
std::cout << "Usage: bio_write <file-read> <file-write>\n";
return 1;
}
bio_in = BIO_new_file(argv[1], "r");
bio_out = BIO_new_file(argv[2], "w");
in_byte = BIO_read(bio_in, buffer, MAX_BUFFER_SIZE);
while (in_byte > 0)
{
std::cout << "Read " << in_byte << " bytes.\n";
out_byte = BIO_write(bio_out, buffer, in_byte);
std::cout << "Wrote " << out_byte << " bytes.\n";
if (in_byte != out_byte)
{
std::cout << "In bytes: " << in_byte << "and Out bytes: " << out_byte << " are not equal.\n";
BIO_free(bio_in);
BIO_free(bio_out);
return 1;
}
in_byte = BIO_read(bio_in, buffer, MAX_BUFFER_SIZE);
}
BIO_free(bio_in);
BIO_free_all(bio_out);
return 0;
}
I am not able to figure out what am I missing here.
I am currently using the C++ to implement my code. The idea is I want to read a wav file through a program and then output its waveform on the screen. I have already found some references there:C++ Reading the Data part of a WAV file. and here is my code of reading the audio file. I have no idea of how to generate the waveform .
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
using std::string;
using std::fstream;
typedef struct WAV_HEADER
{
/* for the part of RIEF Chunk Descriptor */
uint8_t RIFF[4]; // RIFF Header Magic header
uint32_t ChunkSize; // RIFF Chunk Size
uint8_t WAVE[4]; // WAVE Header
/* for the part of "fmt" subChunk */
uint8_t fmt[4]; // FMT header
uint32_t Subchunk1Size; // Size of the fmt chunk
uint16_t AudioFormat; // Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM
uint16_t NumOfChan; // Number of channels 1=Mono 2=Sterio
uint32_t SamplesPerSec; // Sampling Frequency in Hz
uint32_t bytesPerSec; // bytes per second
uint16_t blockAlign; // 2=16-bit mono, 4=16-bit stereo
uint16_t bitsPerSample; // Number of bits per sample
/* For the part of "data" subChunk */
uint8_t Subchunk2ID[4]; // "data" string
uint32_t Subchunk2Size; // Sampled data length
}wav_hdr;
int getFileSize(FILE* inFile);
int main(int argc, char* argv[])
{
wav_hdr wavHeader;
int headerSize = sizeof(wav_hdr), filelength = 0;
const char* filePath;
string input;
if (argc <= 1)
{
cout << "Input wave file name: ";
cin >> input;
cin.get();
filePath = input.c_str();
}
else
{
filePath = argv[1];
cout << "Input wave file name: " << filePath << endl;
}
FILE* wavFile = fopen(filePath, "r");
if (wavFile == nullptr)
{
fprintf(stderr, "Unable to open wave file: %s\n", filePath);
return 1;
}
//Read the header
size_t bytesRead = fread(&wavHeader, 1, headerSize, wavFile);
cout << "Header Read " << bytesRead << " bytes." << endl;
if (bytesRead > 0)
{
//Read the data
uint16_t bytesPerSample = wavHeader.bitsPerSample / 8; //Number of bytes per sample
uint64_t numSamples = wavHeader.ChunkSize / bytesPerSample; //How many samples are in the wav file?
static const uint16_t BUFFER_SIZE = 4096;
int8_t* buffer = new int8_t[BUFFER_SIZE];
while ((bytesRead = fread(buffer, sizeof buffer[0], BUFFER_SIZE / (sizeof buffer[0]), wavFile)) > 0)
{
/** DO SOMETHING WITH THE WAVE DATA HERE **/
cout << "Read " << bytesRead << " bytes." << endl;
}
delete [] buffer;
buffer = nullptr;
filelength = getFileSize(wavFile);
cout << "File is :" << filelength << " bytes." << endl;
cout << "RIFF header :" << wavHeader.RIFF[0] << wavHeader.RIFF[1] << wavHeader.RIFF[2] << wavHeader.RIFF[3] << endl;
cout << "WAVE header :" << wavHeader.WAVE[0] << wavHeader.WAVE[1] << wavHeader.WAVE[2] << wavHeader.WAVE[3] << endl;
cout << "FMT :" << wavHeader.fmt[0] << wavHeader.fmt[1] << wavHeader.fmt[2] << wavHeader.fmt[3] << endl;
cout << "Data size :" << wavHeader.ChunkSize << endl;
// Display the sampling Rate from the header
cout << "Sampling Rate :" << wavHeader.SamplesPerSec << endl;
cout << "Number of bits used :" << wavHeader.bitsPerSample << endl;
cout << "Number of channels :" << wavHeader.NumOfChan << endl;
cout << "Number of bytes per second :" << wavHeader.bytesPerSec << endl;
cout << "Data length :" << wavHeader.Subchunk2Size << endl;
cout << "Audio Format :" << wavHeader.AudioFormat << endl;
// Audio format 1=PCM,6=mulaw,7=alaw, 257=IBM Mu-Law, 258=IBM A-Law, 259=ADPCM
cout << "Block align :" << wavHeader.blockAlign << endl;
cout << "Data string :" << wavHeader.Subchunk2ID[0] << wavHeader.Subchunk2ID[1] << wavHeader.Subchunk2ID[2] << wavHeader.Subchunk2ID[3] << endl;
}
fclose(wavFile);
return 0;
}
// find the file size
int getFileSize(FILE* inFile)
{
int fileSize = 0;
fseek(inFile, 0, SEEK_END);
fileSize = ftell(inFile);
fseek(inFile, 0, SEEK_SET);
return fileSize;
}
I would have left this as a comment with code gists and not an answer since it doesn't answer your question directly but I don't have enough reputation for this.
I did what you're trying to do with Qt, most of my code comes from Qt's documentation. You need to find the peak value of the samples and then draw that. Let me share some code that could give you an idea on how you might want to do it.
void Waveform::appendSamples()
{
buffer = audioDecoder->read();
qreal peak = getPeakValue(buffer.format());
const qint16 *data = buffer.constData<qint16>();
int count = buffer.sampleCount() / 2;
for (int i = 0; i < count; i += 1200){ // I want 40 samples per second currently assuming 48kHz
double val = data[i]/peak;
samples.append(val * 300); // *300 for scaling
}
}
qreal Waveform::getPeakValue(const QAudioFormat &format)
{
qreal ret(0);
if (format.isValid()){
switch (format.sampleType()) {
case QAudioFormat::Unknown:
break;
case QAudioFormat::Float:
if (format.sampleSize() != 32)
ret = 0;
else
ret = 1.00003;
break;
case QAudioFormat::SignedInt:
if (format.sampleSize() == 32)
ret = INT_MAX;
else if (format.sampleSize() == 16)
ret = SHRT_MAX;
else if (format.sampleSize() == 8)
ret = CHAR_MAX;
break;
case QAudioFormat::UnSignedInt:
if (format.sampleSize() == 32)
ret = UINT_MAX;
else if (format.sampleSize() == 16)
ret = USHRT_MAX;
else if (format.sampleSize() == 8)
ret = UCHAR_MAX;
break;
default:
break;
}
}
return ret;
}
For the drawing part in Qt (probably not useful to you)
QSGNode* WaveformRenderer::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
QSGSimpleRectNode *n = static_cast<QSGSimpleRectNode *>(oldNode);
if(!n){
n = new QSGSimpleRectNode();
n->setColor(Qt::red);
}
QVector<double> samples = wav->getSamples(); //retrieve the samples
int numberOfSamples = samples.size();
setItemWidth(qreal(numberOfSamples * 2)); //signal stuff for qml
for(int i = 0; i < numberOfSamples; ++i){
QSGSimpleRectNode *temp = new QSGSimpleRectNode();
temp->setColor(Qt::green);
temp->setRect(i * 2, height()/2 - samples[i], 2, samples[i] * 2);
n->appendChildNode(temp);
}
return n;
}
I am trying to read a large amount of data (~TB) from two solid state drives (SSDs) (ideally unformatted) and combine the data by a certain algorithm and write it back to another SSD. Initially I implemented a program that reads from two FORMATTED hard drives (OS sees it) and writes to another formatted hard drive. I was able to get about 450 MB/Sec speed (for the whole program). I was using fread() to read data from SSDs.
Then I implemented it with reading from two UNFORMATTED SSDs and writing to a formatted SSD and I am only getting about 200 MB/sec. I am still using fread() and I am puzzled why the speed is slower. To read unformatted hard drives I have to run in the Admin mode and use HANDLE and then cast it to a file pointer by the time I read bytes. So, once the correct hard drives are found the code is the same and I am using freads(). The code is listed below for a test program I used to measure the speed of the formatted vs unformatted reads. In this program I am getting about 200 MB/sec for UNFORMATTED hard drive reads and 500 MB/sec for FORMATTED hard drive reads.
Formatted read program.
while (tempCounter < frames_to_process) //
{
if (fread(frame_header_A, 1, 212052, pFile_A) != 212052) {
printf("Couldn't read 212052 Bytes\n");
if (feof(pFile_A))
{
printf("End of File reached while reading the frame\n");
cout << "Num iterations " << tempCounter << endl;
}
if (ferror(pFile_A))
{
printf("Error reading file while reading for the frame\n");
}
time2 = chrono::high_resolution_clock::now();
time_span = chrono::duration_cast<chrono::duration<double>>(time2 - time1);
cout << "time to create imagery files " << setprecision(10) << time_span.count() << " seconds" << endl << endl;
exit(0);
return 0;
}
tempCounter++;
//let's Check whether the variable end with 0xBCB55757
container_count_A = 1;
container_count_B = 2;
if ((frame_header_A[212048] == (char)0xBC) && (frame_header_A[212049] == (char)0xB5) && (frame_header_A[212050] == (char)0x57) && (frame_header_A[212051] == (char)0x57))
{
unsigned int byte_1 = frame_header_A[27];
unsigned int byte_2 = frame_header_A[26];
unsigned int byte_3 = frame_header_A[25];
unsigned int byte_4 = frame_header_A[24];
}
}
Unformatted reads program. Essentially, it iterates though all connected hard drives and find the specific hard drive A and B using a certain pattern. After that the HANDLE is casted to a regular file pointer and then reuses the code above (formatted case)
FILE *pFile_A = NULL;
FILE *pFile_B = NULL;
FILE* f = NULL;
ofstream writeBinary_Combine;
writeBinary_Combine.open(argv[2], ofstream::out | ofstream::binary);
//
LPCTSTR dsksrc = L"\\\\.\\PhysicalDrive";
wchar_t dsk[512] = L"";
int fd;
bool channel_A_found = false;
bool channel_B_found = false;
char frame_header_A[212052]; //seems I can't have another
char frame_header_B[212052];
unsigned int container_count_A = 1;
unsigned int container_count_B = 2;
char* frame_header_test = new char[212052]; // for some reason I am running out of static memory; so I am using heap to alleviate it ???
HANDLE hDisk;
for (int i = 0; i < 8; i++)
{
swprintf(dsk, 511, L"%s%d", dsksrc, i);
hDisk = CreateFile(dsk, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hDisk == INVALID_HANDLE_VALUE)
{
printf("%s%d%s", "couldn't open the drive ", i, "\n");
CloseHandle(hDisk);
}
else
{
printf("%s%d%s", "successfully open the drive ", i, "\n");
fd = _open_osfhandle((intptr_t)hDisk, _O_RDONLY);
char buff_test[500000];
if (fd != -1)
{
f = _fdopen(fd, "rb");
int ret_code = 0;
char drive_header[512];
fread(drive_header, 1, 512, f);
if ((drive_header[510] == (char)0x55) && (drive_header[511] == (char)0xAA)) // test for a formatted drive; is there other identifiers?
{
//bootable drive; not an unformatted drive no need to keep on searching
//_close(fd);
}
else
{
fseek(f, 0, SEEK_SET);
ret_code = find_BCB55757(f, i);
if (ret_code != -1)
{
fseek(f, 0, SEEK_SET);
fread(buff_test, 1, ret_code, f);
fread(frame_header_test, 1, 212052, f);
unsigned int readout_B = 1;
unsigned int cmdout_B = 2;
unsigned int byte_1 = frame_header_test[115];
unsigned int byte_2 = frame_header_test[114];
unsigned int byte_3 = frame_header_test[113];
unsigned int byte_4 = frame_header_test[112];
readout_B = ((byte_4 << 24) & 0xff000000) | ((byte_3 << 16) & 0x00ff0000) | ((byte_2 << 8) & 0x0000ff00) | (byte_1 & 0x000000ff);
byte_1 = frame_header_test[123];
byte_2 = frame_header_test[122];
byte_3 = frame_header_test[121];
byte_4 = frame_header_test[120];
cmdout_B = ((byte_4 << 24) & 0xff000000) | ((byte_3 << 16) & 0x00ff0000) | ((byte_2 << 8) & 0x0000ff00) | (byte_1 & 0x000000ff);
//cout << readout_B << " " << cmdout_B << endl;
size_t result_1 = 0;
if (readout_B == (cmdout_B - 1))
{
channel_B_found = true;
fseek(f, 0, SEEK_SET); //this is the only way to do it
result_1 = fread(buff_test, 1, ret_code, f);
if (result_1 != (size_t)ret_code)
{
cout << "reading error 1 " << endl;
cout << "read bytes " << result_1 << endl;
}
result_1 = fread(frame_header_B, 1, 212052, f);
if (result_1 != (size_t)212052)
{
cout << "reading error 2" << endl;
cout << "read bytes " << result_1 << endl;
}
pFile_B = f;
byte_1 = frame_header_B[27];
byte_2 = frame_header_B[26];
byte_3 = frame_header_B[25];
byte_4 = frame_header_B[24];
cout << "found B" << endl;
}
else
{
channel_A_found = true;
fseek(f, 0, SEEK_SET); //this is the only way to do it
result_1 = fread(buff_test, 1, ret_code, f);
if (result_1 != (size_t)ret_code)
{
cout << "reading error 5" << endl;
cout << "read bytes " << result_1 << endl;
}
result_1 = fread(frame_header_A, 1, 212052, f);
if (result_1 != (size_t)212052)
{
cout << "reading error 6" << endl;
cout << "read bytes " << result_1 << endl;
}
pFile_A = f;
byte_1 = frame_header_A[27];
byte_2 = frame_header_A[26];
byte_3 = frame_header_A[25];
byte_4 = frame_header_A[24];
cout << "found A" << endl;
}
}
//fclose(f);
}
}
else
{
_close(fd);
}
}
if (channel_A_found && channel_B_found)
{
cout << "both drives found" << endl;
break;
}
}// then reuse the code from the formatted case
Here are my questions.
1) why is the speed in the unformatted case lot slower although I am using the same fread(). Does it have to do with setting up reading physical drives the HANDLE
2) Is there a way to improve the speed of the unformatted hard drives? should I be using read() instead of fread() in the unformatted case?
I appreciate any help or ideas!
The following code only saves the first 7 bytes to the file correctly and the remaining 3072-7=3065 bytes are incorrect. "correct" meaning the same value as stored in 'data'.
#define byte unsigned char
void bytesToImage(byte width, byte height, byte* data, size_t byte_count, char* fileNameWithoutExtension)
{
{
std::ofstream file("k3000", std::ios::binary);
file.write((char *)data, 3000);
}
}
However this code does save the first 500 bytes correctly:
#define byte unsigned char
void bytesToImage(byte width, byte height, byte* data, size_t byte_count, char* fileNameWithoutExtension)
{
{
std::ofstream file("k500", std::ios::binary);
file.write((char *)data, 500);
}
}
data has a length of 3072 and the function is called as follows:
size_t imageByteCount = 32 * 32 * 3;
byte* imageBufferOut = (byte*)malloc(sizeof(byte) * imageByteCount);
//(imageBufferOut is initialized...)
bytesToImage(32, 32, imageBufferOut, imageByteCount, "img");
Please excuse the redundant parameters, I have removed as much as possible to try find the bug.
Hex dumps:
Try adding some more instrumentation. For example:
{
cout << "before:";
for (int i = 0; i < 16; ++i)
cout << ' ' << std::hex << int(data[i]);
cout << '\n';
std::ofstream file("k3000", std::ios::binary);
if (file)
cout << "opened\n";
else
cout << "couldn't open\n";
file.write((char *)data, 3000);
file.flush();
if (file)
cout << "wrote ok\n";
else
cout << "write failed\n";
cout << "after:";
for (int i = 0; i < 16; ++i)
cout << ' ' << std::hex << int(data[i]);
cout << '\n';
}
I ask user for input and write this data to disk. However I want the user to be able to update some of this data. It writes the data the first pass of the loop. But the second loop is not updating the description. Here is the code:
#include <iostream>
struct LabData {
int recordNumber;
char desc[16];
};
int main(int argc, const char * argv[]) {
// insert code here...
FILE *file = fopen("myfile.txt", "wb+");
if(file == 0)
std::cout << "ERROR FILE IS NULL!";
for(int i = 0; i < 10; i++)
{
LabData lb;
lb.recordNumber = i;
std::cout << "Enter a description: ";
std::cin.getline(lb.desc, 15);
if(fwrite(&lb, sizeof(lb), 1, file) != 1)
std::cout <<" ERROR IN WRITE!";
}
LabData lb;
for(int i = 9; i >= 0; i--)
{
fseek(file, i * sizeof(LabData), SEEK_SET);
fread(&lb, sizeof(LabData), 1, file);
if(lb.recordNumber != i)
std::cout << "Wrong record!";
else
{
std::cout << "Record number: " << lb.recordNumber << " Description: " << lb.desc << std::endl;
std::cout << "Enter new record description: ";
std::cin.getline(lb.desc, 15);
if(fwrite(&lb, sizeof(lb), 1, file) != 1)
std::cout <<" ERROR IN WRITE!";
}
}
for(int i = 0; i < 10; i++)
{
LabData lb;
fseek(file, i * sizeof(LabData), SEEK_SET);
fread(&lb, sizeof(LabData), 1, file);
std::cout << "Record number: " << lb.recordNumber << " Description: " << lb.desc << std::endl;
}
fclose(file);
return 0;
}
you need to put fseek(file, i * sizeof(LabData), SEEK_SET); before writing into the file, in the second loop,
std::cout << "Record number: " << lb.recordNumber << " Description: " << lb.desc << std::endl;
std::cout << "Enter new record description: ";
std::cin.getline(lb.desc, 15);
fseek(file, i * sizeof(LabData), SEEK_SET);
if(fwrite(&lb, sizeof(lb), 1, file) != 1)
std::cout <<" ERROR IN WRITE!";
Once you read from the file, you have to seek back to rewrite the data in same place.