LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-23-2018, 10:14 PM   #1
Jerry Mcguire
Member
 
Registered: Jul 2009
Location: Hong Kong SAR
Distribution: RedHat, Fedora
Posts: 201

Rep: Reputation: 31
Efficient way to pass socket data to structured data structs


In the old times when decoding some messages in the socket using `read`.

Code:
ssize_t read( int fd, void *buf, size_t count );
The senior programmers would get angry if you set count to 1. They would advocate to bulk read a chunk of data into a buffer and move the pointer along when decoding the buffer. This is what I have believed in up to this very date.

If the socket data is structured, I would simply define the struct and cast over the buffer.

Code:
typedef struct certain_data {
  int32_t a;
  int32_t b;
} certain_data_t;
Hooray! This is efficient enough.

However when the socket data is unstructured and breaks the byte-alignment, the old time method does not work?

For example, the protocol is something like this:
Code:
int32_t time;
uint8_t cType;
uint16_t len;
char name[len];
Things get nasty:
1) a single byte 'cType' is inserted which breaks the byte-alignment in my own data struct. I cannot simply cast the buffer.
2) the socket protocol adopts a variable length field. I cannot simply read the 'name' field without looking at 'len'.

Eventually I'll have to do a lot of expensive memcpy.

What would you suggest to tackle efficiently?
 
Old 04-24-2018, 02:53 AM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,878
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
There is a tool for this in libc: FILE. You can use fdopen, fread, fgetc and so on.
 
Old 04-24-2018, 07:00 AM   #3
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,679
Blog Entries: 4

Rep: Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947Reputation: 3947
Compilers will by default insert alignment-bytes ("slack bytes") into structures for more-efficient access, but you can in various ways specify structure-by-structure that this should not be done. (In Pascal, for instance, the keyword is packed.)

- - -

Also, if the API is in any way public or might be used by different systems, you probably want to serialize the data e.g. with JSON or YAML. Something as basic as "little/big-endianness" or native word-size can torpedo such things, making the tiny "extra overhead" justifiable. These days, "efficiency" probably doesn't matter anymore, but robustness and transportability may well might.

Last edited by sundialsvcs; 04-24-2018 at 12:59 PM.
 
Old 04-25-2018, 04:34 AM   #4
camp0
Member
 
Registered: Dec 2016
Location: Dublin
Distribution: Fedora
Posts: 70

Rep: Reputation: 4
The key for send structs over network is to use packed on them so they will be align. Here is an example

Code:
struct dns_header {
        uint16_t	xid;           
	uint8_t 	rd :1; // recursion desired
    	uint8_t 	tc :1; // truncated message
    	uint8_t 	aa :1; // authoritive answer
    	uint8_t 	opcode :4; // purpose of message
    	uint8_t 	qr :1; // query/response flag
    	uint8_t 	rcode :4; // response code
    	uint8_t 	cd :1; // checking disabled
    	uint8_t 	ad :1; // authenticated data
    	uint8_t 	z :1; // its z! reserved
    	uint8_t 	ra :1; // recursion available
        uint16_t       	questions;       
        uint16_t       	answers;       
        uint16_t       	authorities;
	uint16_t	additionals;     
	uint8_t		data[0];
} __attribute__((packed));

Last edited by camp0; 04-25-2018 at 04:36 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Monitoring data passing on USB bus & copying data (dumping) to hard drive (forking an identical data stream) cilbuper Programming 4 12-11-2017 01:58 PM
Efficient data copy from PCIe device to RAM in kernel PeterWurmsdobler Linux - Kernel 6 07-16-2010 10:18 AM
Efficient kernel<->userspace data transfering maverik Programming 2 05-31-2008 02:24 AM
LXer: Efficient rsyncrypto hides remote sync data LXer Syndicated Linux News 0 02-01-2008 03:40 PM
cannot read data at server socket, though client socket sends it jacques83 Linux - Networking 0 11-15-2005 01:58 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:47 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration