Comment lire / écrire des sockets UNIX dans le bon sens?

Je veux implémenter les fonctionnalités de cette commande bash qui lit / écrit sur un socket UNIX :

echo „READ “ | nc -U /tmp/socket 

cette commande produit la sortie suivante:

 Click::ControlSocket/1.3 200 Read handler 'debug_handler.ping' OK DATA 0 

Mon implémentation actuelle de c / c ++ ressemble à ceci:

monprogramme.hh

 class Myprogram { public: Myprogram(int argc, char** argv); ~Myprogram() { }; private: foo(); int sockfd; int len; sockaddr_un address; }; 

myprogram.cc

 Myprogram::foo() { sockfd = socket(AF_UNIX, SOCK_STREAM, 0); address.sun_family = AF_UNIX; strcpy(address.sun_path, "/tmp/socket"); len = sizeof(address); if(connect(sockfd, (sockaddr*)&address, len) == -1) return; std::ssortingng args = "READ "; if (write(sockfd, args.c_str(), sizeof(args.c_str())) == -1){ std::cout << "Error" << std::endl; return; } int n; char ret_value[200]; do { n = read(sockfd, ret_value, 200); std::cout << std::string(ret_value) << std::endl; std::cout << "n=" << std::to_string(n) < 0); close(sockfd); } 

Je n’ai que cette sortie:

 Click::ControlSocket/1.3 n=26 

le prochain appel read () ne revient pas et le programme attend. J’ai beaucoup essayé de lire le socket, le même résultat, alors ce serait génial si quelqu’un pouvait me donner une idée de ce que je fais mal.

 std::ssortingng args = "READ "; 

le serveur attend une nouvelle ligne (écho ajoute un par défaut), donc:

 std::ssortingng args = "READ \n"; 

Aussi

 char ret_value[200]; do { n = read(sockfd, ret_value, 200); 

devrait être plus comme

 const size_t buflen = 200; char ret_value[buflen+1]; do { n = read(sockfd, ret_value, buflen); if (n < 0) // error else ret_value[n] = 0; 

et cette ligne

  *ret_value+= n; 

ne semble pas clair - vous incrémentez le premier octet de ret_value par n pour quelle raison?

Essayez quelque chose de plus comme ceci:

 Myprogram::foo() { sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd == -1) { std::cout << "Error" << std::endl; return; } address.sun_family = AF_UNIX; strcpy(address.sun_path, "/tmp/socket"); if (connect(sockfd, (sockaddr*)&address, sizeof(address)) == -1) { std::cout << "Error" << std::endl; close(sockfd); return; } std::string args = "READ \n"; if (write(sockfd, args.c_str(), args.size())) == -1) { std::cout << "Error" << std::endl; close(sockfd); return; } int n; char ret_value[200]; do { n = read(sockfd, ret_value, sizeof(ret_value)); if (n < 0) { std::cout << "Error" << std::endl; break; } if (n == 0) { break; } std::cout.write(ret_value, n) << std::endl; std::cout << "n=" << n << std::endl; } while (true); close(sockfd); } 

Bien sûr, si vous voulez vraiment que la sortie apparaisse comme l'original, n'ajoutez pas vos propres personnages à cout (sauf peut-être en cas d'erreur):

 int n; char ret_value[200]; do { n = read(sockfd, ret_value, sizeof(ret_value)); if (n < 0) { //std::cout << "Error" << std::endl; break; } if (n == 0) { break; } std::cout.write(ret_value, n); } while (true);