2016-06-08 3 views
0

Я хочу реализовать функциональные возможности этого Баш-команды, чтение/запись к в UNIX сокет:Как правильно читать/писать 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 

вызов следующего чтения() не возвращает и программа ожидает. Я пробовал много читать сокет, все с тем же результатом, , так что было бы здорово, если бы кто-нибудь мог дать мне подсказку, что я делаю неправильно.

+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

Смежные вопросы