Я создаю приложение для iOS, которое делает фотографию и отправляет ее на TCP-сервер, работающий на моем компьютере.Для этого я настраиваю соединение с потоками следующим образом:
func setupCommunication() {
var readStream: Unmanaged<CFReadStream>?
var writeStream: Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
"192.168.1.40" as CFString, 2323, &readStream, &writeStream)
outputStream = writeStream!.takeRetainedValue()
outputStream.schedule(in: .current, forMode: .common)
outputStream.open()
}
Затем, когда я нажимаю кнопку камеры, фотография берется и отправляется через outputStream.Поскольку TCP-сервер не знает, сколько данных он должен прочитать, первые 8 байтов соответствуют размеру изображения, и изображение отправляется сразу после, как мы можем видеть в этом коде:
func photoOutput(_ output: AVCapturePhotoOutput,
didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
if let image = photo.fileDataRepresentation() {
print(image)
print(image.count)
var nBytes = UInt64(image.count)
let nData = Data(bytes: &nBytes, count: 8)
_ = nData.withUnsafeBytes({
outputStream.write($0, maxLength: nData.count)
})
_ = image.withUnsafeBytes({
outputStream.write($0, maxLength: image.count)
})
outputStream.close()
}
}
На стороне сервера, которая написана на C, я выполняю следующие действия:
Считайте первые 8 байтов, чтобы узнать размер изображения
printf("\n[*] New client connected\n");
while (n_recv < sizeof(uint64_t)) {
if ((n = read(client_sd, buffer, BUF_SIZ)) == -1) {
printf("\n[-] Error reading data from the client\n");
close(client_sd);
close(server_sd);
return 0;
}
n_recv += n;
}
memcpy(&img_size, buffer, sizeof(uint64_t));
printf("\n[+] Client says he's going to send %llu bytes\n", img_size);
Выделите достаточно памяти длясохранить полученное изображение, и если мы уже прочитали какой-либо байт изображения рядом с его размером, скопируйте его.
if ((img_data = (uint8_t *) malloc(img_size)) == NULL) {
printf("\n[-] Error allocating memory for image\n");
close(client_sd);
close(server_sd);
return 0;
}
n_recv -= sizeof(uint64_t);
if (n_recv > 0) {
memcpy(img_data, buffer, n_recv);
}
С этого момента n_recv - это число байт, полученных только для изображения, а невключая первые 8 байтов для размера.Тогда просто читайте до конца.
while (n_recv < img_size) {
if ((n = read(client_sd, buffer, BUF_SIZ)) == -1) {
printf("\n[-] Error reading data from the client\n");
close(client_sd);
close(server_sd);
return 0;
}
memcpy(img_data + n_recv, buffer, n);
n_recv += n;
}
printf("\n[+] Data correctly recived from client\n");
close(client_sd);
close(server_sd);
В начале это работает довольно хорошо.Фактически, я вижу, что каждый раз получаю правильное число для размера изображения:
Однако я не получаюполное изображение, и сервер просто продолжает ждать заблокирован в функции чтения.Чтобы увидеть, что происходит, я добавил это
printf("%llu\n", n_recv);
внутри цикла для чтения изображения, чтобы посмотреть количество полученных байтов.Он останавливается в середине изображения, по какой-то причине я не могу объяснить:
В чем проблема, вызывающая связь сстоп?Проблема в коде сервера или это связано с приложением iOS?