आप portably struct के भेजने के लिए नेटवर्क पर निम्नलिखित की जरूरत है:
पैक संरचना। जीसीसी और संगत कंपाइलर्स के लिए, __attribute__((packed))
के साथ ऐसा करें।
निश्चित आकार के हस्ताक्षरित पूर्णांक के अलावा किसी अन्य सदस्य का उपयोग न करें, इन आवश्यकताओं को पूरा करने वाले अन्य पैक किए गए ढांचे, या पूर्व में से किसी के सरणी। हस्ताक्षरित पूर्णांक भी ठीक हैं, जब तक कि आपकी मशीन दो पूरक पूरक का उपयोग न करे।
यह तय करें कि आपका प्रोटोकॉल पूर्णांक के छोटे-बड़े-एंडियन एन्कोडिंग का उपयोग करेगा या नहीं। उन पूर्णांक को पढ़ने और लिखते समय रूपांतरण करें।
इसके अलावा, आकार 1 या अन्य नेस्टेड पैक किए गए ढांचे वाले लोगों को छोड़कर पैक की गई संरचना के सदस्यों के पॉइंटर्स न लें। this answer देखें।
एन्कोडिंग और डिकोडिंग का एक सरल उदाहरण निम्नानुसार है।यह मानता है कि बाइट ऑर्डर रूपांतरण फ़ंक्शन hton8()
, ntoh8()
, hton32()
, और ntoh32()
उपलब्ध हैं (पूर्व दो नो-ऑप हैं, लेकिन स्थिरता के लिए)।
#include <stdint.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
// get byte order conversion functions
#include "byteorder.h"
struct packet {
uint8_t x;
uint32_t y;
} __attribute__((packed));
static void decode_packet (uint8_t *recv_data, size_t recv_len)
{
// check size
if (recv_len < sizeof(struct packet)) {
fprintf(stderr, "received too little!");
return;
}
// make pointer
struct packet *recv_packet = (struct packet *)recv_data;
// fix byte order
uint8_t x = ntoh8(recv_packet->x);
uint32_t y = ntoh32(recv_packet->y);
printf("Decoded: x=%"PRIu8" y=%"PRIu32"\n", x, y);
}
int main (int argc, char *argv[])
{
// build packet
struct packet p;
p.x = hton8(17);
p.y = hton32(2924);
// send packet over link....
// on the other end, get some data (recv_data, recv_len) to decode:
uint8_t *recv_data = (uint8_t *)&p;
size_t recv_len = sizeof(p);
// now decode
decode_packet(recv_data, recv_len);
return 0;
}
जहां तक बाइट क्रम रूपांतरण कार्यों का संबंध है, आपके सिस्टम के htons()
/ntohs()
और htonl()
/ntohl()
16- और 32-बिट पूर्णांकों, क्रमशः के लिए इस्तेमाल किया जा सकता, करने के लिए/परिवर्तित करने के लिए बड़े endian से। हालांकि, मुझे 64-बिट पूर्णांक के लिए किसी भी मानक फ़ंक्शन से अवगत नहीं है, या छोटे एंडियन से/में कनवर्ट करने के लिए। आप my byte order conversion functions का उपयोग कर सकते हैं; यदि आप ऐसा करते हैं, तो आपको BADVPN_LITTLE_ENDIAN
या BADVPN_BIG_ENDIAN
परिभाषित करके अपनी मशीन के बाइट ऑर्डर को बताना होगा।
जहां तक हस्ताक्षरित पूर्णांक का संबंध है, रूपांतरण कार्यों को उसी तरह से कार्यान्वित किया जा सकता है जैसा मैंने लिखा और लिंक किया है (सीधे बाइट्स को स्वैप करना); हस्ताक्षरित हस्ताक्षर करने के लिए बस हस्ताक्षर करें।
अद्यतन: यदि आप एक कुशल द्विआधारी प्रोटोकॉल चाहते हैं, लेकिन बाइट्स के साथ नगण्य पसंद नहीं है, आप की तरह Protocol Buffers (C implementation) कुछ कोशिश कर सकते हैं। यह आपको अलग-अलग फ़ाइलों में अपने संदेशों के प्रारूप का वर्णन करने की अनुमति देता है, और आपके द्वारा निर्दिष्ट प्रारूप के संदेशों को एन्कोड और डीकोड करने के लिए उपयोग किए जाने वाले स्रोत कोड उत्पन्न करता है। मैंने कुछ भी खुद को लागू किया, लेकिन बहुत सरल बनाया; my BProto generator और some examples देखें (उपयोग उदाहरण के लिए .bproto फ़ाइलें, और addr.h देखें)।
स्रोत
2011-11-03 20:16:58
मैं इस विधि को आज़माउंगा, मैं सिर्फ यह पूछना चाहता हूं कि क्या मैं सिर्फ स्प्रिंटफ का उपयोग करता हूं और संरचना के तत्वों को अलग करने और सॉकेट को भेजने के लिए एक डेलीमीटर का उपयोग करके स्ट्रिंग में सभी डेटा लिखता हूं और फिर प्रत्येक तत्व को निकालने के लिए स्ट्रोक का उपयोग करता हूं दूसरी ओर ? क्या यह एक व्यवहार्य समाधान भी होगा? – user434885
हां, sprintf काम करेगा, लेकिन * केवल * पूर्णांक के लिए; यदि आप इस विधि का उपयोग करते हुए एक स्ट्रिंग (यानी कच्चे बाइट्स सरणी) भेजना चाहते हैं, तो आपको उन्हें बाइट्स की सरणी के रूप में देखना होगा और प्रत्येक बाइट को एक पूर्णांक में परिवर्तित करना होगा, बीच में रिक्त स्थान डालना होगा। उदाहरण के लिए, "एबीसी" को "9 7 98 99" के रूप में भेजा जाएगा। यह बेहतर हो सकता है क्योंकि डीबगिंग के दौरान विश्लेषण करना किसी भी तरह से आसान है, लेकिन यह एन्कोड/डीकोड करने के लिए बेकार है, खासकर यदि आप डिकोडिंग करते समय पूर्ण त्रुटि जांचना चाहते हैं। –
आपके दूसरे बुलेट बिंदु के पीछे प्रेरणा क्या है - केवल हस्ताक्षरित पूर्णांक का उपयोग करना। अक्षरों, बाइट्स या तार भेजने के लिए संरचना (या चार सरणी) में वर्णों का उपयोग क्यों नहीं किया जा सकता था? – aaronsnoswell