In PHP network programming, socket_recvmsg and socket_sendmsg are two advanced low-level socket functions. Compared to socket_recv and socket_send, these two functions offer many additional capabilities, such as handling control messages and multi-buffer I/O. When used together appropriately, they can greatly enhance the efficiency and flexibility of data transmission, making them suitable for implementing high-performance network services.
This article introduces the usage of these two functions and provides a practical example to help you understand their application.
socket_recvmsg
Used to receive messages from a socket with scatter read functionality, allowing data to be read into multiple buffers at once. It also supports receiving ancillary data such as control messages and flags.
socket_sendmsg
Used to send messages through a socket with gather write functionality, allowing data from multiple buffers to be sent in a single operation.
Both functions use a common structure called msghdr, which encapsulates the details for sending or receiving data including buffers and control messages.
The traditional socket_recv and socket_send functions are simple and convenient for basic data transmission but have limitations. They only support single buffer I/O, lack support for control messages, and are less flexible in handling complex scenarios. In contrast, socket_recvmsg and socket_sendmsg provide a much more powerful and flexible approach.
The advantages include:
Efficient multi-buffer I/O, reducing the need for multiple calls.
Support for control messages, enabling advanced socket options and features.
Greater flexibility in implementing custom protocols and handling metadata.
iovec buffer array
This is used by socket_sendmsg to specify multiple data buffers to send. The iovec array describes the individual buffers.
msghdr message header structure
The msghdr structure describes the message, including the destination address, iovec buffers, ancillary data, and flags. It is the core data structure used by these functions.
Control message handling
This enables the receipt and sending of ancillary data such as socket options and file descriptors.
Address and port specification
These are set inside the msghdr structure to specify the source or destination network endpoint.
The following example demonstrates how to send and receive multiple buffers using socket_sendmsg and socket_recvmsg in PHP.
<?php
// Create UDP socket
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
socket_bind($sock, '0.0.0.0', 12345);
// Destination address
$addr = 'gitbox.net'; // Example domain
$port = 12345;
// Prepare data to send in multiple buffers
$data1 = "Hello, ";
$data2 = "world!";
// Construct iovec array
$iov = [
["iov_base" => $data1, "iov_len" => strlen($data1)],
["iov_base" => $data2, "iov_len" => strlen($data2)],
];
// Construct msghdr
$msg = [
"msg_name" => [$addr, $port], // Destination address
"msg_iov" => $iov,
"msg_iovlen" => count($iov),
"msg_control" => null,
"msg_controllen" => 0,
"msg_flags" => 0,
];
// Send message
socket_sendmsg($sock, $msg);
// Prepare buffers to receive data
$buf1 = str_repeat("\0", 16);
$buf2 = str_repeat("\0", 16);
$riov = [
["iov_base" => &$buf1, "iov_len" => 16],
["iov_base" => &$buf2, "iov_len" => 16],
];
$rmsg = [
"msg_name" => null, // Receive source address
"msg_iov" => $riov,
"msg_iovlen" => count($riov),
"msg_control" => null,
"msg_controllen" => 0,
"msg_flags" => 0,
];
// Receive message
socket_recvmsg($sock, $rmsg);
echo "Received: " . trim($buf1) . trim($buf2) . PHP_EOL;
socket_close($sock);
?>
If you are working on advanced PHP network programming, mastering these functions can significantly enhance your ability to handle complex messaging scenarios efficiently.