Говнокод
|
\|/
http:
1. Отсутствует буферизация чтения, во временную переменную. (Данные могут приходить не целиком, а кусками, их нужно класть во временную переменную, после чего разбивать по спецсимволу.)
2. Отсутствует буферизация записи в сокет. (Сокет не обязан записать все данные, он может записать 1 байт из 100000000000 байтов, которые ему дали, а так как сокет не блокирующий, к тому времени еще данные на запись появляются. Требуется стек.)
3. Нету отлова WSAEWOULDBLOCK и других прелестей.
4. Отсутствие полной проверки на ошибки, в том числе через сокгетопт SO_ERROR. Отсуствие таймаутов.
Если все это не учесть могут выползать баги мешками.
Это конечно личное ИМХО, но я тут решил серьезно изучить сокеты на
php.
Вот запиливаю функцию которая правильно бы записывала в сокет.
Тут функция пока не поддерживает множественные коннекты, может работать только с 1 подключением. И буфер 1. При множественных конектах нужно делать общий буфер наверно в виде массива, но как по нормальному определить размер выделенной памяти под этот массив... сказать сложно.
Работает оно следующим образом. Когда мой некоторый код, записывает данные, на самом деле он буферизируется, вызовов write_socket может быть за 1 итерацию цикла много, и чтобы лишний раз не дергать буферизирую все данные, затем, когда происходит новая итерация цикла вызываю write_socket(null, true) и все данные которые уместились в socket_tcp_sendspace (При условии, что буфер записи свободен) разом отправляются, естественно данные фрагментируются, и при следующей итерации уже остаток доставляется. Так же пока не допилил отлов WSAEWOULDBLOCK, чтобы более корректно было. Так же перед write_socket(null, true) стоит socket_select проверяющий доступность сокета на запись, зачем дергать функцию, если на другом конце стоит воздушный модем с пингом 40к и каналом 16 кб сек.
private function write_socket($cmd, $buffered = false)
{
if($buffered === false)
{
if(strlen($this->write_buffer) < $this->options['write_buffer_size'])
{
$this->write_buffer .= $cmd.'|';
return true;
}
else
{
return false;
}
}
else
{
if($this->write_buffer === null)
return false;
$data_length = strlen($this->write_buffer);
if($data_length < $this->socket_tcp_sendspace)
$current_data = &$this->write_buffer;
else
$current_data = substr($this->write_buffer, 0, $this->socket_tcp_sendspace);
$sent_length = socket_write($this->handle_connection, $current_data, $this->socket_tcp_sendspace);
if($data_length === $sent_length)
$this->write_buffer = null;
else
$this->write_buffer = substr($this->write_buffer, $sent_length);
return true;
}
}
$this->socket_tcp_sendspace = socket_get_option($this->handle_connection, SOL_SOCKET, SO_SNDBUF);
Так получаю размер буфера отправки. На винде он примерно 8к с копейками, на юниксах (фрибизди) можно буфер побольше сделать у меня 32к стоит. И вообще шоколад =)