Сервер сокетов домена UNIX C ++ не может вернуть данные клиенту

Вот простой эхо-сервер, над которым я работаю, сервер примет запрос от клиента и вернет то, что клиент отправляет на него. Программа отлично работает с socat, но зависнет при использовании моего собственного клиента.

Проблема в том, что мой старый код состоит в том, что я использую read вместо read_some, read будет блокировать канал до тех пор, пока он не прочитает определенное количество байтов или не получит исключение из разорванного канала, тогда как read_some будет читать кусок за раз. В обновленной версии используются read_some прочитать входной поток и проверить, является ли последний символ, прочитанный программой, \0, если это \0, это означает, что он достигает конца команды, поэтому он будет возвращаться обратно. Это работает, потому что я передаю только строковые литералы и в канале нет двоичных данных.

Код сервера есть

using namespace std;

const char* epStr = "/tmp/socketDemo";

int main() {
namespace local = boost::asio::local;

boost::asio::io_service io_service;

::unlink(epStr);

local::stream_protocol::endpoint ep(epStr);
local::stream_protocol::acceptor acceptor(io_service, ep);

while(1) {
local::stream_protocol::socket *socket = new local::stream_protocol::socket(io_service);
acceptor.accept(*socket);

char buf[2048] = {0};
boost::system::error_code error;

size_t len = 0;
while(1) {
len += socket->read_some(boost::asio::buffer(buf + len, 2048 - len));
cout << "read " << len << endl;
if (buf[len] == '\0') {
break;
}
}

cout << "read " << len << " bytes" << endl;
cout << buf << endl;

boost::asio::write(*socket, boost::asio::buffer(buf, len), boost::asio::transfer_all());
}
}

При тестировании сервера с socat команда, например

echo "12345" | socat - UNIX-CONNECT:/tmp/socketDemo

он вернет желаемый результат.

Мой код клиента

const char* epStr = "/tmp/socketDemo";

int main(int argc, const char* argv[]) {
boost::asio::io_service io_service;
boost::asio::local::stream_protocol::endpoint ep(epStr);
boost::asio::local::stream_protocol::socket socket(io_service);

socket.connect(ep);

boost::asio::write(socket, boost::asio::buffer(argv[1], strlen(argv[1])), boost::asio::transfer_all());

char buf[1024] = {0};

size_t len = 0;
while(1) {
len += socket.read_some(boost::asio::buffer(buf + len, 2048 - len));
std::cout << "read " << len << std::endl;
if (buf[len] == '\0') {
break;
}
}

std::cout << "read " << len << " bytes\n";

std::cout << buf << std::endl;

socket.close();

Когда выполняется клиент, сначала оба не имеют выходных данных, после того как я убил клиента, сервер выведет, что он читает n байтов, и получит исключение из-за разбитого канала.

Может ли это быть вызвано read функция на сервере? Если да, есть ли способ сообщить ему, сколько данных он должен прочитать, не отправляя размер блока данных в начале каждого сообщения? Мне также интересно, почему socat может работать с этим сервером без проблем? Спасибо!

0

Решение

Мне также интересно, почему socat может работать с этим сервером без каких-либо
проблема?

Возможно, потому что socat закрывает сокет, а ваш клиент — нет.

Если да, есть ли способ дать ему знать, сколько данных он должен прочитать
без отправки размера порции данных в начале каждого
сообщение?

Например, чтение одного байта за раз, пока вы не прочитаете символ конца сообщения, предполагая, что вы определяете / используете протокол, который включает EOM.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]