socket_write
(PHP 4 >= 4.1.0, PHP 5, PHP 7)
socket_write — Запись в сокет
Описание
Функция socket_write() записывает в сокет socket данные из указанного буфера buffer .
Список параметров
Буфер, который будет записан.
Необязательный параметр length может указывать другое число байт, записываемых в сокет. Если это число больше, чем длина буфера, оно будет молча урезано до длины буфера.
Возвращаемые значения
Возвращает количество байт, успешно записанных в сокет или FALSE в случае возникновения ошибки. Код ошибки может быть получен при помощи функции socket_last_error() . Этот код может быть передан функции socket_strerror() для получения текстового описания ошибки.
Совершенно нормально для функции socket_write() возвращать ноль, что означает, что ни одного байта не было записано. Пожалуйста, используйте оператор === для проверки значения на FALSE в случае ошибки.
Примечания
socket_write() не обязательно записывает все байты из указанного буфера. Нормально то, что, в зависимости от сетевых буферов и т. д., только некоторое количество данных, даже один байт, будет записан, хотя ваш буфер больше. Вы должны следить за тем, чтобы непреднамеренно не забыть передать остаток ваших данных.
Смотрите также
- socket_accept() — Принимает соединение на сокете
- socket_bind() — Привязывает имя к сокету
- socket_connect() — Начинает соединение с сокетом
- socket_listen() — Прослушивает входящие соединения на сокете
- socket_read() — Читает строку байт максимальной длины length из сокета
- socket_strerror() — Возвращает строку, описывающую ошибку сокета
socket_write
socket_write — записывает в сокет.
Описание
int socket_write (resource socket, string buffer [, int length])
Предупреждение! | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
15.02.2015, 16:54 | |||||||||||||||||||||
Невозможно создать Socket: Socket sock = new Socket(someHostString,somePortInt); Как при помощи ф-ий read/write записать в файл, а потом считать с него read(); write(); Read/write property read()/write() блокировки |
|||||||||||||||||||||
15.02.2015, 17:22 | 2 | ||||||||||||||||||||
РешениеПротокол TCP, — а я полагаю, что речь о нем, — гарантирует целостность socket_write(PHP 4 >= 4.1.0, PHP 5) socket_write — Запись в сокет ОписаниеФункция socket_write() записывает в сокет socket данные из указанного буфера buffer . Список параметровБуфер, который будет записан. Необязательный параметр length может указывать другое число байт, записываемых в сокет. Если это число больше, чем длина буфера, оно будет молча урезано до длины буфера. Возвращаемые значенияВозвращает количество байт, успешно записанных в сокет или FALSE в случае возникновения ошибки. Код ошибки может быть получен при помощи функции socket_last_error() . Этот код может быть передан функции socket_strerror() для получения текстового описания ошибки. Совершенно нормально для функции socket_write() возвращать ноль, что означает, что ни одного байта не было записано. Пожалуйста, используйте оператор === для проверки значения на FALSE в случае ошибки. Примечанияsocket_write() не обязательно записывает все байты из указанного буфера. Нормально то, что, в зависимости от сетевых буферов и т. д., только некоторое количество данных, даже один байт, будет записан, хотя ваш буфер больше. Вы должны следить за тем, чтобы непреднамеренно не забыть передать остаток ваших данных. Смотрите также
Ошибка соединения с ошибкой сокета: сокет. Что не так с моим кодом JavaЯ пытаюсь создать и поддерживать TCP-соединение с хостом из автономного приложения Java. Локальный порт и порт сервера одинаковы = 8999. После подключения мне нужно отправить сообщение на сервер: username=fred&password=abcd . Код для создания сокетов и отправки сообщений выглядит следующим образом: Но соединение не сохраняется. При отладке я обнаружил следующую ошибку: Примечание. Эта же программа успешно запускается при подключении к фиктивному серверу (localhost) на моем компьютере, где я могу получать и отправлять сообщения. Там нет причин для в while циклы в первую очередь. Это сообщение для входа: его нужно отправить только один раз. Сервер почти наверняка не ожидает второго от подключенного входа, поэтому он закрывается. isConnected() не является допустимым тестом для присутствия соединения. Единственным допустимым тестом является отсутствие IOException такого как тот, который вы получаете, что означает, что сверстник закрыл соединение. И когда вы получаете такое исключение, все, что вы можете сделать, это закрыть сокет и перестать пытаться. Повторная попытка бессмысленна: соединение прошло. Socket.isConnected() сообщает только о состоянии Socket. Не соединение. Вы подключили этот разъем, поэтому он подключен. NB Вы должны использовать одни и те же потоки для жизни сокета, а не создавать новые сообщения. @EJP @weston Проблема была решена после многих хитов и испытаний. Рабочий код выглядит следующим образом: Но у меня нет идеи, почему этот код работает, а оригинал — нет. Любые предложения будут высоко ценится. И большое спасибо за опору с моими запросами и дублирующими сообщениями. @EJP относительно вашей мысли о том, что сервер закрывает соединение между получением STX и следующей строкой, вы правы. Сервер не сразу закрыл соединение; это было только во время отладки (когда серверу было достаточно времени для анализа байтов), что я заметил, что это так. не работает PHP socket_writeЯ пытаюсь отправить простое сообщение из PHP-скрипта на Java-сервер, и все прекрасно соединяется друг с другом, пока я не попытаюсь использовать socket_write на PHP. Если я попытаюсь, все скрипт перестает работать, то, что должно произойти до socket_write тоже. Вот мой код: При комментировании socket_write страница из скрипта PHP показывает это: и журнал Java показывает это: Это имеет смысл, потому что нет сообщения для чтения, поэтому он ждет другого соединения. Но socket_write не комментируется, журнал Java показывает «Ожидание соединения», а страница PHP пуста, что означает, что он не выполняет ни один из сценариев. Так что я сделал не так? socket_write(PHP 4 >= 4.1.0, PHP 5) socket_write — Write to a socket ОписаниеThe function socket_write() writes to the socket from the given buffer. Список параметровThe buffer to be written. The optional parameter length can specify an alternate length of bytes written to the socket. If this length is greater then the buffer length, it is silently truncated to the length of the buffer. Возвращаемые значенияReturns the number of bytes successfully written to the socket или FALSE в случае возникновения ошибки. The error code can be retrieved with socket_last_error() . This code may be passed to socket_strerror() to get a textual explanation of the error. It is perfectly val >socket_write() to return zero which means no bytes have been written. Be sure to use the === operator to check for FALSE in case of an error. Примечанияsocket_write() does not necessarily write all bytes from the given buffer. It’s valid that, depending on the network buffers etc., only a certain amount of data, even one byte, is written though your buffer is greater. You have to watch out so you don’t unintentionally forget to transmit the rest of your data. Смотрите также
интервью Раввина Борода https://cursorinfo.co.il/all-news/rav. [b]Мой комментарий: [center][Youtube]CLegyQkMkyw[/Youtube][/center] Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ): Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором) [center][b]Сон разума народа России [/center] [center][Youtube]CLegyQkMkyw[/Youtube][/center] Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ): Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором) [center][b]Сон разума народа России [/center] Способ 3 — Использование неблокирующих сокетовТретий способ основан на использовании неблокирующих сокетов (nonblocking sockets) и функции select. Сначала разберёмся, что такое неблокирующие сокеты. Сокеты, которые мы до сих пор использовали, являлись блокирующими (blocking). Это название означает, что на время выполнения операции с таким сокетом ваша программа блокируется. Например, если вы вызвали recv, а данных на вашем конце соединения нет, то в ожидании их прихода ваша программа «засыпает». Аналогичная ситуация наблюдается, когда вы вызываете accept, а очередь запросов на соединение пуста. Это поведение можно изменить, используя функцию fcntl. sockfd = socket(AF_INET, SOCK_STREAM, 0); fcntl(sockfd, F_SETFL, O_NONBLOCK); Эта несложная операция превращает сокет в неблокирующий. Вызов любой функции с таким сокетом будет возвращать управление немедленно. Причём если затребованная операция не была выполнена до конца, функция вернёт -1 и запишет в errno значение EWOULDBLOCK. Чтобы дождаться завершения операции, мы можем опрашивать все наши сокеты в цикле, пока какая-то функция не вернёт значение, отличное от EWOULDBLOCK. Как только это произойдёт, мы можем запустить на выполнение следующую операцию с этим сокетом и вернуться к нашему опрашивающему циклу. Такая тактика (называемая в англоязычной литературе polling) работоспособна, но очень неэффективна, поскольку процессорное время тратится впустую на многократные (и безрезультатные) опросы. Чтобы исправить ситуацию, используют функцию select. Эта функция позволяет отслеживать состояние нескольких файловых дескрипторов (а в Unix к ним относятся и сокеты) одновременно. int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); FD_CLR(int fd, fd_set *set); FD_ISSET(int fd, fd_set *set); FD_SET(int fd, fd_set *set); Функция select работает с тремя множествами дескрипторов, каждое из которых имеет тип fd_set. В множество readfds записываются дескрипторы сокетов, из которых нам требуется читать данные (слушающие сокеты добавляются в это же множество). Множество writefds должно содержать дескрипторы сокетов, в которые мы собираемся писать, а exceptfds — дескрипторы сокетов, которые нужно контролировать на возникновение ошибки. Если какое-то множество вас не интересуют, вы можете передать вместо указателя на него NULL. Что касается других параметров, в n нужно записать максимальное значение дескриптора по всем множествам плюс единица, а в timeout — величину таймаута. Структура timeval имеет следующий формат. int tv_sec; // секунды int tv_usec; // микросекунды Поле «микросекунды» смотрится впечатляюще. Но на практике вам не добиться такой точности измерения времени при использовании select. Реальная точность окажется в районе 100 миллисекунд. Теперь займёмся множествами дескрипторов. Для работы с ними предусмотрены функции FD_XXX, показанные выше; их использование полностью скрывает от нас детали внутреннего устройства fd_set. Рассмотрим их назначение. FD_ZERO(fd_set *set) — очищает множество set FD_SET(int fd, fd_set *set) — добавляет дескриптор fd в множество set FD_CLR(int fd, fd_set *set) — удаляет дескриптор fd из множества set FD_ISSET(int fd, fd_set *set) — проверяет, содержится ли дескриптор fd в множестве set Если хотя бы один сокет готов к выполнению заданной операции, select возвращает ненулевое значение, а все дескрипторы, которые привели к «срабатыванию» функции, записываются в соответствующие множества. Это позволяет нам проанализировать содержащиеся в множествах дескрипторы и выполнить над ними необходимые действия. Если сработал таймаут, select возвращает ноль, а в случае ошибки -1. Расширенный код записывается в errno. Программы, использующие неблокирующие сокеты вместе с select, получаются весьма запутанными. Если в случае с fork мы строим логику программы, как будто клиент всего один, здесь программа вынуждена отслеживать дескрипторы всех клиентов и работать с ними параллельно. Чтобы проиллюстрировать эту методику, я в очередной раз переписал код сервера с использованием select. Новая версия приведена в листинге 3. Эта программа, также написана на C++ (а не на C). В программе использовался класс set из библиотеки STL языка C++, чтобы облегчить работу с набором дескрипторов и сделать её более понятной. Листинг 3. Код сервера (неблокирующие сокеты и select). Сокеты¶Сокеты (англ. socket — разъём) — название программного интерфейса для обеспечения обмена данными между процессами. Процессы при таком обмене могут исполняться как на одной ЭВМ, так и на различных ЭВМ, связанных между собой сетью. Сокет — абстрактный объект, представляющий конечную точку соединения. Принципы сокетов¶Каждый процесс может создать слушающий сокет (серверный сокет) и привязать его к какому-нибудь порту операционной системы (в UNIX непривилегированные процессы не могут использовать порты меньше 1024). Слушающий процесс обычно находится в цикле ожидания, то есть просыпается при появлении нового соединения. При этом сохраняется возможность проверить наличие соединений на данный момент, установить тайм-аут для операции и т.д. Каждый сокет имеет свой адрес. ОС семейства UNIX могут поддерживать много типов адресов, но обязательными являются INET-адрес и UNIX-адрес. Если привязать сокет к UNIX-адресу, то будет создан специальный файл (файл сокета) по заданному пути, через который смогут сообщаться любые локальные процессы путём чтения/записи из него (см. Доменный сокет Unix). Сокеты типа INET доступны из сети и требуют выделения номера порта. Обычно клиент явно подсоединяется к слушателю, после чего любое чтение или запись через его файловый дескриптор будут передавать данные между ним и сервером. Основные функции¶
socket()¶Создаёт конечную точку соединения и возвращает файловый дескриптор. Принимает три аргумента: domain указывающий семейство протоколов создаваемого сокета
type
protocol Протоколы обозначаются символьными константами с префиксом IPPROTO_* (например, IPPROTO_TCP или IPPROTO_UDP). Допускается значение protocol=0 (протокол не указан), в этом случае используется значение по умолчанию для данного вида соединений. Функция возвращает −1 в случае ошибки. Иначе, она возвращает целое число, представляющее присвоенный дескриптор. Пример на Python Связывает сокет с конкретным адресом. Когда сокет создается при помощи socket(), он ассоциируется с некоторым семейством адресов, но не с конкретным адресом. До того как сокет сможет принять входящие соединения, он должен быть связан с адресом. bind() принимает три аргумента:
Возвращает 0 при успехе и −1 при возникновении ошибки. Пример на Python Автоматическое получение имени хоста. listen()¶Подготавливает привязываемый сокет к принятию входящих соединений. Данная функция применима только к типам сокетов SOCK_STREAM и SOCK_SEQPACKET. Принимает два аргумента:
После принятия соединения оно выводится из очереди. В случае успеха возвращается 0, в случае возникновения ошибки возвращается −1. Пример на Python accept()¶Используется для принятия запроса на установление соединения от удаленного хоста. Принимает следующие аргументы:
Функция возвращает дескриптор сокета, связанный с принятым соединением, или −1 в случае возникновения ошибки. Пример на Python connect()¶Устанавливает соединение с сервером. Некоторые типы сокетов работают без установления соединения, это в основном касается UDP-сокетов. Для них соединение приобретает особое значение: цель по умолчанию для посылки и получения данных присваивается переданному адресу, позволяя использовать такие функции как send() и recv() на сокетах без установления соединения. Загруженный сервер может отвергнуть попытку соединения, поэтому в некоторых видах программ необходимо предусмотреть повторные попытки соединения. Возвращает целое число, представляющее код ошибки: 0 означает успешное выполнение, а −1 свидетельствует об ошибке. Пример на Python Передача данных¶Для передачи данных можно пользоваться стандартными функциями чтения/записи файлов read и write, но есть специальные функции для передачи данных через сокеты: Нужно обратить внимание, что при использовании протокола TCP (сокеты типа SOCK_STREAM) есть вероятность получить меньше данных, чем было передано, так как ещё не все данные были переданы, поэтому нужно либо дождаться, когда функция recv возвратит 0 байт, либо выставить флаг MSG_WAITALL для функции recv, что заставит её дождаться окончания передачи. Для остальных типов сокетов флаг MSG_WAITALL ничего не меняет (например, в UDP весь пакет = целое сообщение). send, sendto — отправка данных. |