Считывание и запись в сокет в режиме виртуального соединения
Считывание с сокета с установлением логического (виртуального) соединения обладает следующей особенностью: примитив возв-ращает результат после считывания, по крайней мере, одного байта; в результате этого, число считанных байтов часто меньше требуемого числа. Следовательно, необходимо зациклить примитив считывания, чтобы добиться продолжения... Точнее, вот что возвращает вызов примитива read () (или recv (), или recvfrom ()):
-1: если соединение разорвано или не существует;
>0: было получено определенное число байтов; необходимо организовать цикл считывания для продолжения работы (конечно же, нет необходимости в организации цикла, если ожидаемое количество байтов уже получено);
0: удаленная программа выполнила close (), на чем и остановилась. Функция записи возвращает результат после того, как буфер выходных данных быдет передан через TCP. Программа предупреждается о возможной ошибке сигналом SIGPIPE, о котором речь пойдет далее.
Ниже в данной главе читатель найдет две процедуры: reads () и writes (), позволяющие читать и записывать n-байтов в сокет. Для этого организуется цикл по числу считанных или записанных байтов, до получения необходимого их количества. Две эти процедуры, применяемые повсеместно, использованы во многих примерах в данной главе.
ПРОГРАММА 25 /* процедуры reads() и writes() для чтения и записи в сокет в режиме виртуального соединения */
#include <stdio.h>
/* запись в сокет буфера, состоящего из пос байт */ int writes(sock, pbuf, noc) register int sock; /* дескриптор сокета */ register char *pbuf; /* буфер */ register int noc; /* число записываемых байт */ { int nreste, necrit; nreste = noc; while (nreste > 0) { necrit = write(sock, pbuf, nreste); if (necrit < 0) return(necrit); nreste -= necrit; pbuf += necrit; } return(noc-nreste); } /* считывание в буфер пос байт из сокета */ int reads(sock, pbuf, noc) register int sock; /* дескриптор сокета */ register char *pbuf; /* буфер */ register int noc; /* число считываемых байт */ { int nreste, nlit;
nreste = noc; while (nreste > 0) { nlit = read(sock, pbuf, nreste); if (nlit < 0) return(nlit); else if (nlit == 0) break; nreste -= nlit; pbuf += nlit; } return(noc-nreste); }