Я пытаюсь получить некоторые json данные с сервера, но моя программа иногда выводит неожиданную строку, хотя я проверяю ее несколько раз, чтобы убедиться, что у нее правильное начало и конец.
Это моя отправка и функции чтения с веб-сервера:
int total_to_send = request.size();
int sent;
int total_sent = 0;
while(total_sent < total_to_send) {
sent = send(_socket, &request.data()[total_sent], total_to_send - total_sent, 0);
if(sent <= 0) {
break;
}
total_sent += sent;
}
if(sent <= 0) {
printf("[Thread #%i] Error occurred when sending request... (%i/%i, %i @ %s)\n", total_sent, total_to_send, sent, path.c_str());
break;
}
int read;
int total_read = 0;
while(true) {
read = recv(_socket, &buffer[total_read], sizeof(char) * 1024, 0);
total_read += read;
if(read <= 0)
break;
if(total_read > 0 && buffer[total_read - 1] == '}')
break;
}
if(read < 0 || total_read == 0) {
printf("[Thread #%i] Error occurred when reading response... (%i, %i @ %s)\n", ThreadID, read, total_read, path.c_str());
break;
}
Буфер - это char buffer[1024000];
. Я почти уверен, что в буфере достаточно места для ответа.
Я пытаюсь проверить правильность начала и окончания ответа следующим образом:
if(buffer[total_read - 1] != '}') {
printf("[Thread #%i] Invalid response from the server... ('%c', %i, %i @ %s)\n", ThreadID, buffer[total_read - 1], read, total_read, path.c_str());
break;
}
int start_pos = -1;
for(int i = 0; i < total_read; ++i) {
if(buffer[i] == '{') {
start_pos = i;
break;
}
}
if(start_pos == -1) {
printf("[Thread #%i] Invalid response from the server... (%i, %i @ %s)\n", ThreadID, read, total_read, path.c_str());
break;
}
if(step == 0) {
static const char NonExistingResource[11] = "Not found.";
if((total_read - start_pos) == 10) {
int s = 0;
for(int c = 0; c < 11; ++c) {
if(NonExistingResource[c] == buffer[start_pos + c]) {
++s;
}
}
if(s == 10) {
printf("[Thread #%i] The resource %i does not exist...\n", ThreadID, StartID);
step = 9;
break;
}
}
}
Все работает, как ожидалось - ну, по крайней мере, в большинстве случаев это так. Я добавляю в буфер немного больше информации, а затем пытаюсь ее записать:
buffer[total_read] = '\n';
buffer[start_pos - 1] = '#';
fwrite(&buffer[start_pos - 1], sizeof(char), (total_read - start_pos) + 2, file);
Проблема начинается позже. В 99% случаев я записываю в файл действительный json (например, #{"id":3,"numbers":[1, 3, 7],"time":1323423610}
), но в оставшемся 1% мой код записывает все прочитанное содержимое. И это содержимое следует за предыдущей строкой без добавления каких-либо разрывов строки или символа #. Например,
#{"id":1,"numbers":[1, 3, 7],"time":1323423610}
#{"id":2,"numbers":[2, 4, 8],"time":1323423610}
#{"id":3,"numbers":[9],"time":1323423610}HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
Content-Length: 88
Connection: keep-alive
Date: Fri, 10 Jul 2020 07:53:42 GMT
Server: openresty
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, HEAD, POST, PUT, DELETE, OPTIONS
Access-Control-Expose-Headers: ETag, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After, Content-Length, Content-Range
Cache-Control: public, max-age=21600
x-memc: MISS, STORE
x-memc-key: 8c68004d1219af73acc5312e3fdf554e
x-memc-age: 0
x-memc-expires: 21600
Last-Modified: 2020-04-11 11:27:09 +0000
X-Cache: Hit from cloudfront
Age: 4478
{"id":4,"numbers":[5],"time":1323423610}
#{"id":5,"numbers":[6],"time":1323423610}
Теперь мой код явно находится на al oop. Он отправляет несколько запросов, используя один и тот же сокет, и воссоздает сокет, когда сервер возвращает ошибку или запросы терпят неудачу. Кроме этого, я никогда не пытаюсь изменить буфер, за исключением того, что иногда сбрасываю его, но это не должно вызывать никаких проблем, потому что я не редактирую его между чтением и fwrite.
Кроме того, я сталкиваюсь с этим случайным образом. Иногда программа работает так, как ожидалось, и выводит то, что я хочу, а иногда она просто помещает туда весь ответ! Я не могу найти шаблон, которому нужно следовать.
Между прочим, код предназначен для одновременной работы с несколькими потоками, но каждый поток имеет свой собственный сокет и ФАЙЛ *, поэтому никакой другой поток не мешает процессу записи . Иногда некоторые потоки делают это, а некоторые - нет, хотя я говорю, что нужно отправлять одинаковое количество запросов.
Любая помощь / идеи приветствуются людьми!