Вот простой эхо-сервер, над которым я работаю, сервер примет запрос от клиента и вернет то, что клиент ему отправляет. Программа отлично работает с 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
может без проблем работать с этим сервером? Спасибо!
static
дляepStr
- person Ryan   schedule 05.01.2016read_some
и @llya я решил это. - person bxshi   schedule 05.01.2016