Yuqori darajadagi tillarda datagram paketiga qarash mumkinmi?

Hozirda datagram (udp) paketlarini ba'zi yuqori darajali tilga moslashtiradigan c dasturini ishga tushirishga harakat qilaman. Paketlar o'zgarmaydigan hajmga ega bo'lishlari sababli, ularning o'lchamlarini bildiruvchi aniq raqam bilan boshlanadi. Javobda, MSG_PEEK bayrog'i bilan faqat ushbu qiymatni birinchi marta qabul qilishni taklif qilaman, keyin bir fitting buferini ajratib, paketning qolgan qismini o'qiyman. Kod (soddalashtirilgan) quyidagicha bo'ladi:

// Simplified message format.
struct message {
    int length;
    char[] text;
}
struct message *m = malloc (sizeof(int));

// Read out in just length.
recv (sock, m, sizeof(int), MSG_WAITALL | MSG_PEEK);
int txtlen = ntohl (m->length) * sizeof(char);
int msglen = sizeof(int) + txtlen;

// Read complete packet.
m = realloc (m, msglen);
read (sock, m, msglen);
m->text[txtlen] = '\0';

// Show result.
printf("%s\n", &m->text);

Men juda katta tamponni ajratish va odatda kattaroq paketlar kelmasligiga umid qilaman. Pyaton yoki java kabi oliy darajadagi tillarda oldindan imkoni bo'lgan datagramda ko'rib chiqish yoki uning to'liq uzunligini aniqlash kabi bir narsa bormi?

0
juda liyitli resurslarga ega ko'milgan tizim bo'lmasa, albatta.
qo'shib qo'ydi muallif Karoly Horvath, manba
UDP paketlari "katta" bo'lolmaydi (qarang: stackoverflow.com/questions/1098897/… ). Bu haqda tashvishlanishingizga ishonchingiz komilmi?
qo'shib qo'ydi muallif Mat, manba

3 javoblar

Katta tamponni ajratish va paketning kattalashib ketishiga umid qilaman.

Bu nimani anglatishini bilmasangiz. Bir UDP paketi bir vaqtning o'zida kelib qoladi, shuning uchun dastlabki tamsayt sizning buferingiz qanchalik katta bo'lishi kerakligini aniqlaydi; u kelgandan keyin "o'smaydi".

Null belgini qo'shganingiz uchun, siz hisob-kitob qilishingiz kerak:

int msglen = sizeof(int) + txtlen + 1;

realloc() foydalanganda ehtiyot bo'ling:

m = realloc (m, msglen);

Agar realloc bajarilmasa, m ni bo'shga o'rnatish kerak. Ya'ni, unga ajratilgan xotiraga faqat sizning murojaatingiz yo'qoladi, shuning uchun hech qachon free() ni qodir qila olmaysiz. Quyidagilarni sinab ko'ring:

void *tmp = realloc(m, msglen)
if (tmp == null) {
 //handle the error
}
m = tmp;

And when you print the data, m->text evaluates to the address of the first character, so you can use

printf("%s\n", m->text);

Shu bilan bir qatorda, sizning strukturangizni aniq o'lcham bilan belgilashingiz mumkin

struct message {
  int length;
  char *text;
}

Keyin matn buferini ajratish uchun malloc() dan foydalanishingiz mumkin:

struct message m;
recv(sock, &m.length, sizeof(int), MSG_WAITALL | MSG_PEEK);
m.text = malloc(m.length + 1);//+1 for the null that you'll append
read(sock, m.text, m.length);
m.text(m.length) = '\0';

printf("%s\n", m.text);
free(m.text);

Sizning loyihangizga omad tilaymiz - tarmoq dasturlash - bu doimo o'rganish tajribasi!

1
qo'shib qo'ydi
Chaqaloq uchun rahmat! Mening javobimda tuzatdim.
qo'shib qo'ydi muallif Adam Liss, manba
Kodni taqqoslashni soddalashtiradigan reallokni tekshirishdan bosh tortdim. Yuqorida aytib o'tilganidek, ikkita o'qish chaqiruvi ikkita paketni o'qiydi va shuning uchun men bir structni ma'qul ko'rdim.
qo'shib qo'ydi muallif XZS, manba

UDP datagrams are limited to 64K, then ethernet frames are 1500 bytes (unless your network is using jumbo frames, which could be up to 9000 bytes). Protocol designers usually try to avoid IP fragmentation, so most likely your incoming packets are small, i.e. less then 1500 bytes.

Men faqat 1472 statik bufer (1500 chekilgan ramkali uzunligi - 20 bayt IP-sarlavhasi - UDP nomidagi 8 bayt) bilan boshlayman. Agar siz o'zboshimchalik bilan protokollar bilan muomala qilishingiz kerak bo'lsa, - bu 64Kgacha tushiradi. Agar siz bunga qodir bo'lmasangiz - haqiqiy hajmlarni MSG_PEEK bilan to'ldiring, ba'zi qulay o'rtacha qiymatlarni toping va malloc (3) .

0
qo'shib qo'ydi
Ha, 64K, albatta, isrof emas, lekin bu kun va yoshda, ba'zi bir ko'milgan/manba cheklangan muhitda bo'lmaguningizcha, bu muammo emas.
qo'shib qo'ydi muallif Nikolai Fetissov, manba
Menimcha, paketning uzunligini belgilaydigan 16-bitli UDP nomidagi maydonda 64K chegarasi paydo bo'ladi. Shunday qilib, bu, albatta, bir saqlash tamponu uchun ahamiyat bering. Biroq, hatto 64K, aslida, u faqat int ni o'qib, kerakli xotira oldindan ma'lum bo'lishi mumkinligini hisobga olib, bir isrof bo'ladi.
qo'shib qo'ydi muallif XZS, manba

Buni nima qilish kerak?

message = (struct message *)malloc(sizeof(struct message));
read(sock, &message->length, sizeof(int);
message->length = ntohl(message->length);
message->text = (char *)malloc(message->length + 1);
read(sock, message->text, message->length);
message->text[message->length] = 0;
0
qo'shib qo'ydi
Afsuski, bu ikki datagramni olgani uchun ishlamaydi. Birinchi o'qilganidan so'ng, butun datagram faqatgina intdan ko'proq bo'lsa ham tashlanadi.
qo'shib qo'ydi muallif XZS, manba