I've been assigned a project in which I need to use Unix Domain Sockets to communicate two-way between a parent and child process. My original approach was to create a child and server, but I was getting some serious issues with connectivity and paths. If anyone would prefer to see that code, I'm willing to provide it.
Anyway, I'm reaching the line in my program where I print out "parent has written", although I'm not entirely convinced that it has because no subsequent reading occurs. I've worked with closing the pipes in different places and changing how I'm reading/writing.
I am now using socketpair() to set up a pair of sockets. I cannot use any other type of IPC other than sockets. This information is brand new to me, so forgive the sloppy code.
Please ignore long #include list, will clean up ASAP.
Again, my current output stops at "Parent wrote to child" and then it keeps running, does not close out, so I think it's the child read waiting to receive something.
My program needs to be able to read and write incredibly long files, so you'll see serialization and parsing work throughout the code. The serialization and parsing works perfectly on a different part of the project, so I know that's not the issue. It's the darn sockets!
Anyway, code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <sys/wait.h>
#include <vector>
#include <fstream>
int main() {
int sockets[2];
std::cout << "Please enter name of text file." << std::endl;
std::string entered_file;
std::cin >> entered_file;
std::string string_to_find;
std::cout << "Please enter the string you'd like to search for." << std::endl;
std::cin >> string_to_find;
int rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
if (rc < 0) {
perror("socketpair");
exit(1);
}
pid_t p;
p = fork();
if (p == 0) //child
{
char ch;
std::string the_file_as_string = "";
std::vector<std::string> lines_with_string;
int r;
while ((r = read(sockets[0], &ch, 1)) > 0) {
the_file_as_string.push_back(ch);
}
std::cout << "Child has read from parent..." << std::endl;
size_t pos = 0;
while(the_file_as_string.find(string_to_find, pos) != std::string::npos) {
pos = the_file_as_string.find(string_to_find, pos+string_to_find.size());
std::string sub = the_file_as_string.substr(0,pos);
int occurrences = 0;
size_t pos2 = 0;
while (sub.find("/0", pos2 ) != std::string::npos) {
pos2 = sub.find("/0", pos2+2);
++ occurrences;
pos += string_to_find.length();
}
occurrences = occurrences;
std::string occurrences_string = std::to_string(occurrences);
lines_with_string.push_back(occurrences_string);
}
std::cout << "child has parsed" << std::endl;
std::string lines_with_string_as_string = "";
for(unsigned int i=0; i<lines_with_string.size(); i++) {
lines_with_string_as_string = lines_with_string_as_string + lines_with_string.at(i) + "/0";
}
int file_size = lines_with_string_as_string.size();
write(sockets[0], lines_with_string_as_string.c_str(), file_size+1);
close(sockets[0]);
std::cout << "child has sent back to parent..." << std::endl;
}
else //parent
{
close(sockets[0]);
std::ifstream myfile;
//open file
myfile.open(entered_file.c_str());
if (!myfile) {
std::cerr << "Unable to open file datafile.txt" << std::endl;
return 1; // call system to stop
}
//here, pass lines to child one by one and return true or false based on if it finds the string
char lines_with_string[100];
char ch;
std::vector<std::string> the_file;
std::vector<int> final_line_numbers;
std::vector<std::string> final_lines;
std::string str;
while (std::getline(myfile, str))
{
the_file.push_back(str);
}
std::string the_file_as_string = "";
for(unsigned int i=0; i<the_file.size(); i++) {
the_file_as_string = the_file_as_string + the_file.at(i) + "/0";
}
int big_size = the_file_as_string.size();
write(sockets[1], the_file_as_string.c_str(), big_size+1);
std::cout << "Parent wrote to the child..." << std::endl;
wait(NULL);
std::string lines_with_string_as_string = "";
int r;
while ((r = read(sockets[1], &ch, 1)) > 0) {
lines_with_string_as_string.push_back(ch);
}
close(sockets[1]);
std::cout << "Parent has read from child..." << std::endl;
std::string delimit = "/0";
size_t pos3 = 0;
while ((pos3 = lines_with_string_as_string.find(delimit)) != std::string::npos) {
std::string token = lines_with_string_as_string.substr(0, pos3);
int token2 = std::stoi(token);
final_line_numbers.push_back(token2);
lines_with_string_as_string.erase(0, pos3 + delimit.length());
}
//match line numbers to array of lines (original)
for(unsigned int i=0; i < final_line_numbers.size(); i++) {
int find_int = final_line_numbers.at(i);
std::string find_string = the_file.at(find_int-1);
std::cout << find_string << std::endl;
final_lines.push_back(find_string);
}
std::sort(final_lines.begin(), final_lines.end());
std::cout << "The final outcome with lines containing " << "'" << string_to_find << "' are:" << std::endl;
for(unsigned int i=0; i<final_lines.size(); i++) {
std::cout << final_lines.at(i) << std::endl;
}
myfile.close();
std::cout << "Program has exited completely." << std::endl;
}
}
MINI VERSION (same issue, says "Parent has written to child..." and then doesn't do anything further, and also doesn't exit:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string>
#include <iostream>
#include <algorithm>
#include <sys/wait.h>
#include <vector>
#include <fstream>
int main() {
int sockets[2];
pid_t p;
socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
p=fork();
if (p < 0) {
perror("forking");
}
else if(p > 0) { //parent
std::string long_string_to_send = "ladjfldjsfljasdfj adjlkjadlsjf a fljasdfladj ljdl aljfajdfljadfadsflajd ajfdlkjslfjadj faldjsljalsdfljdfljadsl jladsfjasflajdflkajfl dasl fjalfjldjsfladsflajdlsfald fjljdfljadfjadfjl djfljadlfj aldjl hello";
int big_size = long_string_to_send.size();
write(sockets[1], long_string_to_send.c_str(), big_size+1);
std::cout << "Parent has written to child..." << std::endl;
wait(NULL);
std::string lines_with_string_as_string = "";
int r;
char ch;
while ((read(sockets[1], &ch, 1)) > 0) {
lines_with_string_as_string.push_back(ch);
}
close(sockets[1]);
std::cout << "Parent has received from child..." << std::endl;
std::cout << "Parent has read the following... " << lines_with_string_as_string << std::endl;
std::cout << "Program has exited completely" << std::endl;
}
else { //child
char ch;
std::string the_file_as_string = "";
int r;
while ((read(sockets[0], &ch, 1)) > 0) {
the_file_as_string.push_back(ch);
}
std::cout << "Child has read from parent..." << std::endl;
std::cout << "Child has read the following... " << the_file_as_string << std::endl;
int file_size = the_file_as_string.size();
write(sockets[0], the_file_as_string.c_str(), file_size+1);
close(sockets[0]);
}
}