клиент сервера отправляет получающую структуру через ошибки необработанных данных Stack Overflow

Я делаю отправку и получение функций для структуры (в моем случае «кадр») через TCP / IP. Но функции, кажется, не работают, и я не могу найти, где мои ошибки. Меня просят хранить все данные в массиве char и отправлять его при получении массива char и преобразовывать их в структуру.

struct frame {
int length;
int * body;
int tail;
};void winsock_client::send_frame(frame f) {
char * arr;
char * tx;
int length = 8 + f.length * sizeof(int);
arr = new char[length];

tx = (char*)&f.length;
for (int i = 0; i < sizeof(int); i++) {
arr[i] = *(tx++);
}

for (int i = 0; i < f.length; i++) {
tx =(char*)&f.body[i];

for (int j = 0; j < sizeof(int); j++) {
arr[4 + i * sizeof(int) + j] = *(tx++);
}
}

tx = (char*)&f.tail;
for (int i = 0; i < sizeof(int); i++) {
arr[4 + f.length * sizeof(int) + i] = *(tx++);
}

send(client_socket, arr, sizeof(arr), 0);
}void winsock_server::receive_frame(frame & f) {
int * rx;
recv(server_socket, rx_buffer, sizeof(rx_buffer), 0);
rx =(int *) &rx_buffer[0];
f.length = *rx;

f.body = new int[f.length];

rx = (int *)&rx_buffer[4];
for (int i = 0; i < f.length; i++) {
f.body[i] = *(rx++);
}

rx = (int*)&rx_buffer[16];
f.tail = *rx;

}

Может кто-нибудь сказать мне, что мои ошибки в моих функциях?

1

Решение

Вы не проверяете возвращаемые значения send() а также recv() чтобы убедиться, что вы действительно отправляете / получаете все, что вы ожидаете. TCP является потоковым транспортом, между отправителями и получателями нет отношения 1: 1, как в UDP. Обе функции могут отправлять / получать меньше байтов, чем запрошено, поэтому вам нужно это обработать.

Кроме того, ваш read_frame() использует буфер фиксированной длины для получения данных, но вы не принимаете во внимание, сколько данных на самом деле отправляется, поэтому ваш буфер может не получить полный кадр, или, что еще хуже, может получить кадр, который больше, чем может содержать ,

Код тоже просто некрасиво читать. Это должно быть переписано.

Попробуйте что-то более похожее на это:

bool sendAll(SOCKET s, const void *buf, int len)
{
const char *pbuf = (const char*) buf;
while (len > 0)
{
int sent = send(s, pbuf, len, 0);
if (sent == SOCKET_ERROR)
return false;
pbuf += sent;
len -= sent;
}
return true;
}

bool winsock_client::send_frame(const frame &f)
{
int size = (2 + f.length) * sizeof(u_long);

char *arr = new char[size];

// multi-byte integers should always be transmitted in network
// byte order to avoid any endian issues across machine boundaries...

u_long *ptr = (u_long*) arr;

*ptr++ = htonl(f.length);

for (int i = 0; i < f.length; ++i)
*ptr++ = htonl(f.body[i]);

*ptr = htonl(f.tail);

bool result = sendAll(client_socket, arr, size);

delete[] arr;

return result;
}

bool recvAll(SOCKET s, void *buf, int len)
{
char *pbuf = (char*) buf;
while (len > 0)
{
int recvd = recv(s, pbuf, len, 0);
if (recvd <= 0) // -1 on error, 0 on disconnect
return false;
pbuf += recvd;
len -= recvd;
}
return true;
}

bool winsock_server::receive_frame(frame &f)
{
u_long temp;

if (!recvAll(server_socket, &temp, sizeof(temp)))
return false;
f.length = ntohl(temp);

u_long *arr = new u_long[f.length+1];

if (!recvAll(server_socket, arr, sizeof(u_long) * (f.length + 1)))
{
delete[] arr;
return false;
}

f.body = new int[f.length];

for(int i = 0; i < f.length; ++i)
f.body[i] = ntohl(arr[i]);

f.tail = ntohl(arr[f.length]);

delete[] arr;

return true;
}

В качестве альтернативы вы можете немного упростить код, если учтите, что сокет уже выполняет свою собственную внутреннюю буферизацию для вас:

bool sendAll(SOCKET s, const void *buf, int len)
{
const char *pbuf = (const char*) buf;
while (len > 0)
{
int sent = send(s, pbuf, len, 0);
if (sent == SOCKET_ERROR)
return false;
pbuf += sent;
len -= sent;
}
return true;
}

bool sendInt(SOCKET s, int value)
{
// multi-byte integers should always be transmitted in network
// byte order to avoid any endian issues across machine boundaries...
u_long temp = htonl(value);
return sendAll(s, &temp, sizeof(temp));
}

bool winsock_client::send_frame(const frame &f)
{
if (!sendInt(client_socket, f.length))
return false;

for (int i = 0; i < f.length; ++i)
{
if (!sendInt(client_socket, f.body[i]))
return false;
}

return sendInt(client_socket, f.tail);
}

bool recvAll(SOCKET s, void *buf, int len)
{
char *pbuf = (char*) buf;
while (len > 0)
{
int recvd = recv(s, pbuf, len, 0);
if (recvd <= 0) // -1 on error, 0 on disconnect
return false;
pbuf += recvd;
len -= recvd;
}
return true;
}

bool recvInt(SOCKET s, int &value)
{
u_long temp;
bool result = recvAll(s, &temp, sizeof(temp));
if (result) value = ntohl(temp);
return result;
}

bool winsock_server::receive_frame(frame &f)
{
if (!recvInt(server_socket, f.length))
return false;

f.body = new int[f.length];

for(int i = 0; i < f.length; ++i)
{
if (!recvInt(server_socket, f.body[i]))
{
delete[] f.body;
return false;
}
}

if (!recvInt(server_socket, f.tail))
{
delete[] f.body;
return false;
}

return true;
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]