2016-06-08 87 views
0

我想要实现读/写一个UNIX插座此bash的命令的功能:如何以正确的方式读取/写入UNIX套接字?

echo „READ <a command>“ | nc -U /tmp/socket 

此命令会生成以下的输出:

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

我现在的C/C++实现看起来像这样:

myprogram.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::string args = "READ <a command>"; 

    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) << std::endl; 
     *ret_value+= n; 
    } while (n > 0); 

    close(sockfd); 
} 

我只得到这样的输出:

Click::ControlSocket/1.3 
n=26 

下一个read()调用不返回,程序等待。 我已经尝试了很多阅读套接字,所有的结果都一样, 所以如果有人能够给我一个提示我做错了什么,那将会很棒。

+0

'的sizeof(args.c_str())'是4或8。 – immibis

+5

'的sizeof(args.c_str())'应该是'args.size()'。 –

+3

C/C++不是一种语言。如果你认为'class'是一个关键字,那么你正在编写C++。 –

回答

2
std::string args = "READ <a command>"; 

服务器正在等待一个新行(回波添加一个默认情况下),所以:

std::string args = "READ <a command>\n"; 

另外

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

应该更像

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; 

和这条线

*ret_value+= n; 

似乎不清楚 - 你正在增加ret_value的第一个字节n为什么?

+1

我还将sizeof(args.c_str())更改为args.size(),如@πάνταῥεῖ所述。但所有提示都很有帮助,谢谢。 – S1J0

1

尝试更多的东西是这样的:

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 <a command>\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); 
} 

当然,如果你真的想要的输出出现就像当初不是没有自己的字符添加到cout(除了可能在错误的情况下):

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); 
+0

这是一个很好的解决方案,谢谢。但是,如果所有行都被读取了,读取函数将不会返回并且程序等待,但仍然存在问题。 – S1J0