Я пытаюсь расширить пример клиента Tcp, разработанного с использованием Ansi C, следуя книге "Сокеты TCP / IP в C". Клиент подключается к Tcp-серверу, предоставляя строки различной длины в зависимости от запроса, предоставленного клиентом (я разработал свой собственный простой протокол). Когда возвращаемые строки имеют короткую длину, все работает нормально. Когда они превышают определенную длину (это происходит, например, с 4 КБ), клиент аварийно завершает работу с ошибкой сегментации.
Сокет обрабатывается с помощью оболочки для потокового ввода / вывода:
FILE *str = fdopen(sock, "r+"); // Wrap for stream I/O
И передача и прием обрабатываются с использованием fwrite () и fread ().
Это вызов, который генерирует ошибку в моем проекте (вызывающая сторона):
uint8_t inbuf[MAX_WIRE_SIZE];
size_t respSize = GetNextMsg(str, inbuf, MAX_WIRE_SIZE); // Get the message
И это реализация функции GetNextMsg (), которая использует для получения и расфасовки данных:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <netinet/in.h>
#include "Practical.h"
/* Read 4-byte length and place in big-endian order.
* Then read the indicated number of bytes.
* If the input buffer is too small for the data, truncate to fit and
* return the negation of the *indicated* length. Thus a negative return
* other than -1 indicates that the message was truncated.
* (Ambiguity is possible only if the caller passes an empty buffer.)
* Input stream is always left empty.
*/
uint32_t GetNextMsg(FILE *in, uint8_t *buf, size_t bufSize)
{
uint32_t mSize = 0;
uint32_t extra = 0;
if (fread(&mSize, sizeof(uint32_t), 1, in) != 1)
return -1;
mSize = ntohl(mSize);
if (mSize > bufSize)
{
extra = mSize - bufSize;
mSize = bufSize; // Truncate
}
if (fread(buf, sizeof(uint8_t), mSize, in) != mSize)
{
fprintf(stderr, "Framing error: expected %d, read less\n", mSize);
return -1;
}
if (extra > 0)
{ // Message was truncated
uint32_t waste[BUFSIZE];
fread(waste, sizeof(uint8_t), extra, in); // Try to flush the channel
return -(mSize + extra); // Negation of indicated size
}
else
return mSize;
}
Я подозреваю, что это может быть связано с тем, что с Tcp отправитель и получатель обрабатывают данные с потоковым поведением, поэтому не гарантируется, что получатель получает все данные одновременно, как, вероятно, предположил простой пример, из которого я начал. На самом деле с короткими струнами все работает. С более длинными строками это не так.
Я сделал упрощенную отладку, вставив printf в качестве первой вещи внутри функции, но когда у меня есть cra sh, это даже не печатается ,
Кажется, что проблема с строкой FILE *, передаваемой в качестве аргумента функции, когда через сокет получено сообщение, более длинное, чем обычно.
Размер буферов намного больше размера длина сообщения, вызывающего проблему (1 МБ против 4 КБ). Я даже пытался увеличить размер буфера сокета с помощью setsockopt:
int rcvBufferSize;
// Retrieve and print the default buffer size
int sockOptSize = sizeof(rcvBufferSize);
if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rcvBufferSize, (socklen_t*)&sockOptSize) < 0)
DieWithSystemMessage("getsockopt() failed");
printf("Initial Receive Buffer Size: %d\n", rcvBufferSize);
// Double the buffer size
rcvBufferSize *= 10;
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &rcvBufferSize,
sizeof(rcvBufferSize)) < 0)
DieWithSystemMessage("setsockopt() failed");
, но это не помогло.
Любые идеи о причине и как я могу это исправить