I am working on a project where I need to convert a string to binary format and implement cyclic redundancy check (crc) on the binary data. The data need to transfer though a client-server communication. I need to provide two files city.txt and country.txt and the data of those two files need to convert first in binary and implemented crc on it and send those files to server and server remove the crc and change it back to string again and send it to client. All this those function work well for the 1st file that I send though the network (city.txt) but for the second file it did not work.
The client side code is
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#define SIZE 2024
// Function to run the CRC service and generate the CRC file
void CRC(const char *inputFile, const char *outputFile) {
pid_t pid = fork();
if (pid < 0) {
perror("[-]Error in fork");
exit(1);
} else if (pid == 0) {
FILE *fp = fopen(outputFile, "w");
if (!fp) {
perror("[-]Error in opening output file");
exit(1);
}
dup2(fileno(fp), STDOUT_FILENO);
fclose(fp);
execlp("./crc", "./crc", inputFile, NULL);
perror("[-]Error in execlp for CRC service");
exit(1);
} else {
wait(NULL);
}
}
void write_file(int sockfd, const char *filename) {
}
void send_file(int sockfd, const char *filename) {
}
int main() {
char *ip = "127.0.0.1";
int port = 8080;
int sockfd, e;
struct sockaddr_in server_addr;
FILE *fp;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");
e = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (e == -1) {
perror("[-]Error in connecting to server");
exit(1);
}
printf("[+]Connected to Server.\n");
CRC("city.txt", "ccity.txt");
sleep(1);
// Send citycrc.txt to the server
fp = fopen("citycrc.txt", "r");
if (fp == NULL) {
perror("[-]Error in reading citycrc.txt");
exit(1);
}
printf("[+]Sending citycrc.txt to the server\n");
send_file(sockfd, "citycrc.txt");
fclose(fp);
printf("[+]citycrc.txt sent successfully.\n");
sleep(1);
// Send countrycrc.txt to the server
fp = fopen("countrycrc.txt", "r");
if (fp == NULL) {
perror("[-]Error in reading countrycrc.txt");
exit(1);
}
printf("[+]Sending countrycrc.txt to the server\n");
send_file(sockfd, "countrycrc.txt");
fclose(fp);
printf("[+]countrycrc.txt sent successfully.\n");
sleep(1);
// Receive crcascii.txt from the server
write_file(sockfd, "crcasciicity.txt");
printf("[+]crcasciicity.txt received successfully.\n");
sleep(1);
printf("[+]Receiving crcasciicountry.txt from the server\n");
write_file(sockfd, "crcasciicountry.txt");
printf("[+]crcasciicountry.txt received successfully.\n");
// Close the connection
close(sockfd);
printf("[+]Connection closed.\n");
return 0;
}
Server side code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define SIZE 5024
// Function to receive a file from the client
void write_file(int sockfd, const char *filename) {
}
void send_file(int sockfd, const char *filename) {
}
// Function to extract, flip MSB, convert to ASCII, and save to ASCII file
void extract_flip_and_save_ascii(const char *inputFile, const char *outputFile) {
}
int main() {
char *ip = "127.0.0.1";
int sockfd, new_sock;
struct sockaddr_in server_addr, new_addr;
socklen_t addr_size;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("[-]Error in socket");
exit(1);
}
printf("[+]Server socket created successfully.\n");
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr.s_addr = inet_addr(ip);
if (bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
perror("[-]Error in bind");
exit(1);
}
printf("[+]Binding successful.\n");
if (listen(sockfd, 10) == 0) {
printf("[+]Listening...\n");
} else {
perror("[-]Error in listening");
exit(1);
}
addr_size = sizeof(new_addr);
new_sock = accept(sockfd, (struct sockaddr*)&new_addr, &addr_size);
if (new_sock < 0) {
perror("[-]Error in accepting connection");
exit(1);
}
printf("[+]Connection accepted.\n");
// Receive citycrc.txt from the client
write_file(new_sock, "citycrc.txt");
printf("[+]citycrc.txt received successfully.\n");
// Receive countrycrc.txt from the client
write_file(new_sock, "countrycrc.txt");
printf("[+]countrycrc.txt received successfully.\n");
// Generate crcasciicity.txt from citycrc.txt
extract_flip_and_save_ascii("citycrc.txt", "crcasciicity.txt");
printf("[+]crcasciicity.txt generated successfully.\n");
// Send crcasciicity.txt to the client
printf("[+]Sending crcasciicity.txt to the client.\n");
send_file(new_sock, "crcasciicity.txt");
printf("[+]crcasciicity.txt sent successfully.\n");
sleep(1);
// Generate crcasciicountry.txt from countrycrc.txt
extract_flip_and_save_ascii("countrycrc.txt", "crcasciicountry.txt");
printf("[+]crcasciicountry.txt generated successfully.\n");
send_file(new_sock, "crcasciicountry.txt");
printf("[+]crcasciicountry.txt sent successfully.\n");
// Close the connection
close(new_sock);
close(sockfd);
printf("[+]Connection closed.\n");
return 0;
}
city.txt has data like Clinton, Greenvile,...
county.txt has data like Canada, Brazil...
citycrc.txt holds binary representation of city.txt file like "10" format.
countrycrc.txt holds binary representation of country.txt file like "10" format.
cityasciicrc.txt takes citycrc.txt as input and do the extract_flip_save_ascii() operation on it and return back Clinton, Greenvile. countryasciicrc.txt takes countrycrc.txt as input and do the extract_flip_save_ascii() operation on it and return back Canada, Brazil.
When I run the server's executable I received the output
[+]Server socket created successfully.
[+]Binding successful.
[+]Listening...
Then I run client's executable I received the output
[+]Server socket created successfully.
[+]Connected to Server.
[+]Generating CRC for city.txt
[+]Generating CRC for country.txt
[+]Sending citycrc.txt to the server
[+]citycrc.txt sent successfully.
[+]Sending countrycrc.txt to the server
[+]countrycrc.txt sent successfully.
[+]Receiving crcasciicity.txt from the server
[+]crcasciicity.txt received successfully.
[+]Receiving crcasciicountry.txt from the server
[-]Error in receiving file size: Success
[+]crcasciicountry.txt received successfully.
[+]Connection closed.
Then if I checked the server's output I found some added output
[+]Connection accepted.
[+]citycrc.txt received successfully.
[+]countrycrc.txt received successfully.
[+]crcasciicity.txt generated successfully.
[+]Sending crcasciicity.txt to the client.
[+]crcasciicity.txt sent successfully.
[-]Error: Not enough bits to extract data part.
[+]crcasciicountry.txt generated successfully.
[+]Sending crcasciicountry.txt to the client.
[-]Error in opening file: No such file or directory
Now I think in the server side getting the output "[-]Error: Not enough bits to extract data part.", is for country.txt. Since I found countrycrc.txt was empty and crcasciicountry.txt was empty,
I did not understand when the codes work well for city.txt, the first file of client-server communication, why it was not working for country.txt?
I am using Ubuntu 20.04, one pc and two terminals to implement client server communication.
Thank you. Any help will be appreciated.
1 Answer 1
You seem to have the wrong idea about the behavior of read() and recv(). Your code is assuming that it will observe a zero-byte read at the end of the data for each individual file transferred, but this is not the case, and no amount of delay between the files will change that. TCP is a stream protocol. It has no built-in sense of messages or other subdivisions, unless you consider individual bytes to be such. End of file on a socket is not about the data transmitted -- it is about whether the socket is still open, such that additional data might still be transmitted.
To be able to recognize the two files as separate units, you need to layer some kind of application protocol on top of the raw byte stream. That could be as simple as putting a byte count in front of each file's data, such that the receiver knows it has reached the end of that file by having read exactly that many (additional) bytes. More complex schemes are possible too, of course.
crcservice_v2program, what does it do? What is the format of its output file? Is it a text file?