There are several types of write operations, write request with authorization, write request without authorization and write command. You can see message sequence charts for those messages here and here.
Write command is a write without acknowledgement and write request is write with acknowledgement. As described in the sequence chart, the ATT will automatically send ack when you transmit write request from the central device. Write Command on the client side should generate BLE_GATTS_EVT_WRITE(WRITE_CMD, data) event on the server (nRF51822) side.
Packet exchange with Write Requests and Indications
When transferring data with a write request from GATT client or with indications from GATT server, then only one packet is sent every other connection event. This is because ATT level acknowledgement must be received for a sent packet before sending another packet. The procedure is as follows:
- Connection event x: Send indication/writeRequest packet
- Connection event x+1: Receive ATT acknowledgement packet
- Connection event x+2: Send indication/writeRequest packet
- Connection event x+3: Receive ATT acknowledgement packet
and so on. So if the chosen BLE connection interval is 7.5ms, then one packet can be sent every 15ms, therefore substantially limiting throughput. The throughput capabilities of the nRF51 with the S110 BLE stack is stated in S110 Softdevice Specification, chapter for BLE Data Throughput.
Packet exchange with Write Commands and Notifications
When transferring data with a write commands from GATT client or with notifications from GATT server, then up to 6 packets can be sent per connection event. No ATT level acknowledgement is required. So if the chosen BLE connection interval is 7.5ms, then up to 6 packets can be sent every 7.5m. The througput is however usually limited by the central device and is different between central devices, see examples on this thread.
Write from GATT client on an Android device
This can be achieved by calling the writeCharacteristic method. To determine what write type is sent, call the setWriteType method with the desired write type option before calling the writeCharacteristic method. When you write to the writeCharacteristic command you need to wait for a callback before calling writeCharacteristic again. The callback will indicate that your data has been buffered in the Android BLE stack and the stack is ready to receive additional data. You should be able to see an implementation of this in the nrf UART v2.0 example provided here.
This example is good for measuring throughput.