#c #sockets #networking #udp
#c #сокеты #сеть #udp
Вопрос:
У меня очень конкретный вопрос по программированию сокетов. Мой код похож на следующий.
struct data_packet{
unsigned char seqnumber;
char data[500];
}
struct data_packet packettosend;
packettosend.seqnumber = '0'
packettosend.data = 'some binary data' (this could be any length from 0 bytes to 500 bytes)
//sender code
char buffer[501];
memcpy(buffer, amp;packettosend, sizeof(packetosend));
int s = sendto(socketfd, buffer, sizeof(buffer), 0 , .......other params);
//receiver code
char recvbuffer[501];
int t = recvfrom(recvsocketdf, recvbuffer, 501, 0 ....other params);
How do I set up my receiver to receive the data and save it on a `struct data_packet`?
Seqnumber — это 1-байтовый символ, а данные могут составлять от 0 байт до 500 байт.
Я использую sendto
для отправки буфера и recvfrom
получения буфера на другом конце.
Как я могу получить свой seqnumber и данные на принимающей стороне? Я очень новичок в программировании на C и Socket. Я ценю любую помощь.
Комментарии:
1. Вам просто нужен буфер для его приема, например, тот, из которого вы его отправили. Затем вы можете проверить полученный вами пакет как a
data_packet
(при условии, что он нужного размера).2. Да, но данные, похоже, имеют мусорные значения в конце, когда отправленные мной данные составляют менее 500 байт
3. Ну, вы получаете только столько, сколько отправили, поэтому чтение чего-либо сверх этого является ошибкой.
recvfrom
сообщает вам, сколько байтов было получено, и вы должны использовать эту информацию.
Ответ №1:
Мое первое предложение — обнулить ваш буфер перед его заполнением и отправкой, просто чтобы избежать мусорных значений. И вам нужно определить протокол — вы можете отправлять и получать только необработанные байты по сети. Сделайте так, чтобы принимающая сторона интерпретировала первый байт как порядковый номер, а остальные — как само фактическое сообщение. Это можно сделать, просто приведя recvbuffer в a struct data_packet
, поскольку базовый байтовый макет тот же.
Ответ №2:
Возможная проблема:
Код, вероятно, записывается за пределы своих границ из-за struct
заполнения.
struct data_packet{
unsigned char seqnumber;
// There maybe padding here.
char data[500];
// There maybe padding here.
}
struct data_packet packettosend;
char buffer[501]; // May be too small for `packettosend`
memcpy(buffer, amp;packettosend, sizeof(packetosend));
Альтернатива: сделать buffer[]
, конечно, достаточно большой
// char buffer[501];
char buffer[sizeof packetosend];
Для отправки только данных, а не, конечно, не каких-либо дополнений:
Упакуйте данные с помощью ключевого слова, специфичного для реализации (если доступно)
// struct data_packet{
packed struct data_packet{
Или выполнить 2 отправки
int s1 = sendto(socketfd, amp;buffer.seqnumber, sizeof buffer.seqnumber, ...);
int s2 = sendto(socketfd, buffer.data, sizeof buffer.data, ...);
Или скопировать тщательно
#define SEQ_DATA (sizeof buffer.seqnumber sizeof buffer.data)
char buffer[SEQ_DATA];
memcpy(buffer, amp;buffer.seqnumber, sizeof buffer.seqnumber);
memcpy(buffer sizeof buffer.seqnumber, buffer.data, sizeof buffer.data);
int s = sendto(socketfd, buffer, sizeof buffer, ...);
Отрегулируйте recvbuffer[]
размер, чтобы соответствовать.
Комментарии:
1. Спасибо вам за то, что уделили этому время. Это выглядит очень многообещающе. Есть определенные условия, которым я должен следовать. Я могу выполнить только 1 отправку. И размер пакета данных, который я получаю, не может превышать 501 байт. Как мне решить эту проблему?
2. @MaheshKhanal Используйте последнее «копировать осторожно»
3. Спасибо. Копирование работает так, как задумано. Я очень ценю это.
Ответ №3:
Я согласен с Деннисом Афанасьевым. Чтобы уточнить стратегию приведения, прочитайте все 501 байт (включая частичное / неполное чтение), а затем преобразуйте в переменную указателя, например:
struct data_packet *dataRecv = (struct data_packet *)amp;recvbuffer[0];
Затем вы можете разыменовать dataRecv для доступа к структуре, как в dataRecv-> seqnumber и dataRecv-> data .