Best way to send packet with RakNet - c++

I was wondering how to send packet to client in client-server architecture with RakNet. In this sample code we have this line:
peer->Send(&bsOut,HIGH_PRIORITY,RELIABLE_ORDERED,0,packet->systemAddress,false);
However, the prototype is the following (from the interface class):
virtual uint32_t Send( const RakNet::BitStream * bitStream,
PacketPriority priority,
PacketReliability reliability,
char orderingChannel,
const AddressOrGUID systemIdentifier,
bool broadcast,
uint32_t forceReceiptNumber=0 )=0;
As you can see, the 5th parameter takes a AddressOrGUID, it means we can send the SystemAddress as in the sample, but also can send the unique GUID of a connected machine.
There is a function called:
RakNet::GetSystemAddressFromGUID();
But I'm not sure if RakNet uses it to convert the GUID we can send as a parameter (I didn't find any use of this method in RakPeer (implemention of RakPeerInterface) and I'm not able to find how buffered packet are sent each tick).
The problem is the following:
The sample code replies directly to the received packet. However, in a game, server has to send information without receiving packet from client. So I don't have access to something like
packet->systemAddress
because there is no received packet.
So I will have to stock something in my Player class to know how to send them packets: SystemAddress or RakNetGUID. RakNetGUID is simpler and lighter to stock than a SystemAddress.
But, if RakNet uses GetSystemAddressFromGUID(), it's not worth because is has a O(log(n)) algorithm.
Do I need to stock the SystemAddress for each Player myself or RakNet::Send() doesn't use this method with a RakNetGUID ?
Thank you!

Ok I just did a mistake by not correctly following condition statement the first time I tried to understand the source code, and because this question is really specific, I think it would be great to look in source code.
The simple answer is Yes, store RakNetGUID in Player class
Details here:
Ok so first, file concerned is RakPeer.cpp only. The starting point is:
uint32_t RakPeer::Send( const RakNet::BitStream * bitStream,
PacketPriority priority,
PacketReliability reliability,
char orderingChannel,
const AddressOrGUID systemIdentifier,
bool broadcast,
uint32_t forceReceiptNumber ) // Line 1366
Then, we have this line where SendBuffered is called:
SendBuffered((const char*)bitStream->GetData(),
bitStream->GetNumberOfBitsUsed(),
priority,
reliability,
orderingChannel,
systemIdentifier, // This is the initial AddressOrGUID
broadcast,
RemoteSystemStruct::NO_ACTION,
usedSendReceipt); // Line 1408
In the method above, we can know the name of the buffer variable:
bufferedCommands.Push(bcs); // Line 4216
And by searching every place where bufferedCommands is used, we find a meaningful method name:
bool RakPeer::RunUpdateCycle(BitStream &updateBitStream ) // Line 5567
We can find a loop that sends every buffered message here:
callerDataAllocationUsed=SendImmediate((char*)bcs->data,
bcs->numberOfBitsToSend,
bcs->priority,
bcs->reliability,
bcs->orderingChannel,
bcs->systemIdentifier, // Initial AddressOfGUID
bcs->broadcast,
true,
timeNS,
bcs->receipt); // Line 5630
RakPeer::SendImmediate() will ask RakPeer::GetSystemIndexFromGuid() to find the appropriate Index:
else if (systemIdentifier.rakNetGuid!=UNASSIGNED_RAKNET_GUID)
remoteSystemIndex=GetSystemIndexFromGuid(systemIdentifier.rakNetGuid); // Line 4300
Finally, this last method will store the index directly in the RakNet::RakNetGUID when found:
unsigned int i;
for ( i = 0; i < maximumNumberOfPeers; i++ )
{
if (remoteSystemList[ i ].guid == input )
{
// Set the systemIndex so future lookups will be fast
remoteSystemList[i].guid.systemIndex = (SystemIndex) i;
return i;
}
} // Line 2440
If we call Send() with RakNetGUID, then it will check if RakNetGUID::systemIndex is set. If yes, it doesn't need to search. Else, it will have a linear searching time O(n) (n = maximumNumbersOfPeers) for the first packet sent.
I wrote this to help people understand how it works if they have the same question in mind.

From the doc : http://www.raknet.net/raknet/manual/systemaddresses.html
It is preferred that you refer to remote systems by RakNetGUID, instead of SystemAddress. RakNetGUID is a unique identifier for an instance of RakPeer, while SystemAddress is not. And it is necessary to exclusively use RakNetGUID if you plan to use the Router2 plugin.
SystemAddress is only the combination of the IP and the port

Related

QTcpSocket sends more data than wanted - Qt/C++

first of all a little background on my situation:
- Qt/C++ UI desktop application
- embedded device (Stm32l4xx family) +ATWINC1500 wifi module
I'm developing the gui application in order to send commands and files to the emdedded device via sockets.
For simple commands I've done all successfully, but for sending files (text files in GCODE format) I am stuck with some issues.
The embedded device has already a socket management(not written by me, so I have not the possibility to modify the way sockets are managed, coming from third party company), and the reception of that type of files is managed in a way that the API waits for every single line of the file being sent, and then wrotes it into a reserved portion of the flash.
My problem is that when I send file from qt Application(by reading each line and and calling write() on the line, in reality my socket sends an entire chunk of the file, like 50 lines, resulting in my device not managing the file reception.
My sending code is this:
void sendGCODE(const QString fileName)
{
QFile *file = new QFile(fileName,this);
bool result = true;
if (file->open(QIODevice::ReadOnly))
{
while (!file->atEnd())
{
QByteArray bytes(file->readLine());
result = communicationSocket->write(bytes);
communicationSocket->flush();
if(result)
{
console->append("-> GCODE line sent:"+ QString(bytes));
}
else
{
console->append("-> Error sending GCODE line!");
}
}
file->close();
}
}
Have anyone of you guys any hints on what I am doing wrong?
I've already searched and someone suggests on other topic that for this purpose it should be better to use UDP instead of TCP sockets, but unfortunately I cannot touch the embedded-device-side code.
thank you all!
EDIT
After suggestions from comments, I've sniffed tcp packets and the packets are sent correctly(i.e. each packet contains a single line). BUT... at the receiver(device), I understood that there is something regarding memory which is not well managed. an example:
sender sends the line "G1 X470.492 Y599.623 F1000" ; receiver receives correctly the string "G1 X470.492 Y599.623 F1000"
next, if the line length is less than the previous sent, i.e. sending "G1 Z5", the receiver receives: "G1 Z5\n\n.492 Y599.623 F1000", so it is clear that the buffer used to store the data packet is not re-initialized from previous packet content, and the new part overwrites the previous values where the remaining part is from the previous packet
I'm trying to figure out how I could reset that part of memory.
This is all wrong. TCP is not a message-oriented protocol. There is no way to ensure that the TCP packets contain any particular amount of data. The receiver code on the device mustn't expect that either - you perhaps misunderstood the receiver's code, or are otherwise doing something wrong (or the vendor is). What the receiver must do is wait for a packet, add the packet's data to a buffer, then extract and process as many complete lines as it can, then move the remaining data to the beginning of the buffer. And repeat that on every packet.
Thus you're looking for the wrong problem at the wrong place, unless your device never ever had a chance of working. If that device works OK with other software, then your "packetized" TCP assumption doesn't hold any water.
Here's how to proceed:
If the device is commercially available and has been tested to work, then you're looking in the wrong place.
If the device is a new product and still in development, then someone somewhere did something particularly stupid and you either need to fix that stupidity, or have the vendor fix it, or hire a consultant to fix it. But just to be completely clear: that's not how TCP works, and you cannot just accept that "it's how it is".

c++ streaming udp data into a queue?

I am streaming data as a string over UDP, into a Socket class inside Unreal engine. This is threaded, and runs in the background.
My read function is:
float translate;
void FdataThread::ReceiveUDP()
{
uint32 Size;
TArray<uint8> ReceivedData;
if (ReceiverSocket->HasPendingData(Size))
{
int32 Read = 0;
ReceivedData.SetNumUninitialized(FMath::Min(Size, 65507u));
ReceiverSocket->RecvFrom(ReceivedData.GetData(), ReceivedData.Num(), Read, *targetAddr);
}
FString str = FString(bytesRead, UTF8_TO_TCHAR((const UTF8CHAR *)ReceivedData));
translate = FCString::Atof(*str);
}
I then call the translate variable from another class, on a Tick, or timer.
My test case sends an incrementing number from another application.
If I print this number from inside the above Read function, it looks as expected, counting up incrementally.
When i print it from the other thread, it is missing some of the numbers.
I believe this is because I call it on the Tick, so it misses out some data due to processing time.
My question is:
Is there a way to queue the incoming data, so that when i pull the value, it is the next incremental value and not the current one? What is the best way to go about this?
Thank you, please let me know if I have not been clear.
Is this the complete code? ReceivedData isn't used after it's filled with data from the socket. Instead, an (in this code) undefined variable 'buffer' is being used.
Also, it seems that the while loop could run multiple times, overwriting old data in the ReceivedData buffer. Add some debugging messages to see whether RecvFrom actually reads all bytes from the socket. I believe it reads only one 'packet'.
Finally, especially when you're using UDP sockets over the network, note that the UDP protocol isn't guaranteed to actually deliver its packets. However, I doubt this is causing your problems if you're using it on a single computer or a local network.
Your read loop doesn't make sense. You are reading and throwing away all datagrams but the last in any given sequence that happen to be in the socket receive buffer at the same time. The translate call should be inside the loop, and the loop should be while(true), or while (running), or similar.

Gnuradio,OOT: correcting send() for tagged stream block?

I need help making a gnuradio OOT module. I am actually trying to extending one code.
I am trying to make 2 TX 1Rx tagged stream block (OOT). For 1Tx 1Rx, it
is working fine. I am trying to extend it. Now the problem is, I am not
being able to configure the send() function. With this code, one transmitter transmits, but other does not work. The subdev specification and frequency and other parameters are allocated correctly. I checked.
If I try make test, it does not show any problem. I checked the every
port of my USRP X310, it is working fine.
Here's the code. I putting a short part which deals with the send and receive buffer.
void
usrp_echotimer_cc_impl::send()
{
// Data to USRP
num_tx_samps = d_tx_stream->send(d_in_send1, total_num_samps,
d_metadata_tx, total_num_samps/(float)d_samp_rate+d_timeout_tx);
num_tx_samps = d_tx_stream->send(d_in_send0, total_num_samps,
d_metadata_tx, total_num_samps/(float)d_samp_rate+d_timeout_tx);
}
int
usrp_echotimer_cc_impl::work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
gr_complex *in0 = (gr_complex *) input_items[0];
gr_complex *in1 = (gr_complex *) input_items[1];
gr_complex *out = (gr_complex *) output_items[0];
// Set output items on packet length
noutput_items = ninput_items[0]=ninput_items[1];
// Resize output buffer
if(d_out_buffer.size()!=noutput_items)
d_out_buffer.resize(noutput_items);
// Send thread
d_in_send0 = in0;
d_in_send1 = in1;
d_noutput_items_send = noutput_items;
d_thread_send =
gr::thread::thread(boost::bind(&usrp_echotimer_cc_impl::send, this));
// Receive thread
d_out_recv = &d_out_buffer[0];
d_noutput_items_recv = noutput_items;
d_thread_recv =
gr::thread::thread(boost::bind(&usrp_echotimer_cc_impl::receive, this));
My system config is X310, daughterboard SBX-120 and I am using UHD-3.9. I checked the subdev specification, gain and frequency assignment. Those
are fine.
For completeness:
This has been asked yesterday on the GNU Radio mailing list; Sanjoy has already gotten two responses:
Martin Braun wrote:
Sorry, Sanjoy,
we'll need some more information before we can give you better
feedback. It's not clear exactly what you're trying to achieve, and
what exactly is failing.
Perhaps this helps getting started:
http://gnuradio.org/redmine/projects/gnuradio/wiki/ReportingErrors
Cheers, Martin
And my answer is a bit longish, but it's available here. In excerpts:
Hi Sanjoy,
I am trying to make 2 TX 1Rx tagged stream block(OOT). For 1Tx 1Rx, it was working fine. I am trying to extend it. Now the problem is, I
am not being able to configure the send() function.
Is there a
particular reason you're creating your own block? Is there a feature
missing on the USRP sink and source that come with gr-uhd?
...
your send() function looks a bit strange; what you're doing is
transmitting two things on a single channel after each other. Also,
what you should be doing (from a programming style point of view) is
pass the buffers you want to send as references or something, but not
save them to class properties and then call send(). To send two
buffers to two different channels, you will need to use a vector
containing the two buffers -- have a look at rx_multi_samples; that of
course recv()s rather than sends(), but the semantics are the same.
...
noutput_items is given to you to let your work now how much it may produce, that's why it's a parameter.
...
There's no reason GNU Radio couldn't already call your work function again while usrp_echotimer_cc_impl::send() hasn't even started to transmit samples. Then, your d_send variables will be overwritten.
...
Since a single X310 is inherently coherent and has the same time, you can simply use a USRP sink and a source, use set_start_time(...) on both with the same time spec, and have your flow graph consume and produce samples in different threads, coherently.

Receiving sms through gprs shield on Arduino

I have been searching all over the net trying to find some example code to see how to listen for sms and read it. I am new to at commands so I am trying to see some examples. My intentions is to listen for sms and read to content. If the message contained the word: 'forward', I want it to run a certain function. I am using a seeedstudio GPRS v1.4 shield with my arduino uno.
I found a library but I am confused on the readSMS() function. The library is found here: https://github.com/Seeed-Studio/Seeeduino_GPRS.
I have the current code:
GPRS gprsTest(8,7,9,9600,"1818XXXXXXXXX");//TX,RX,PWR,BaudRate,PhoneNumber
void setup() {
Serial.begin(9600);
gprsTest.preInit();
delay(1000);
while(0 != gprsTest.init()) {
delay(1000);
Serial.print("init error\r\n");
}
}
void loop() {
//nothing to do
gprsTest.readSMS();
}
My problem is I am not sure of what to put in the parameters for the readSMS function.
According to the api the function takes a int, string, and another int.
int readSMS(int messageIndex, char *message, int length);
Any ideas? Not really any documentation on receiving sms
I am not familiar with Seeed-studio (whose comments in header files are not maintained very well as well, to give you some help) but here is the basic idea:
The received text messages are stored on independent indexes on the selected message memory (SIM or phone which will be modem in your case). New messages usually take the smallest unused index (indexes starting from 1).
There are two methods to detect a new SMS
1) Modem sends a string on output port to indicate new SMS (like an interrupt)
2) You have to read the count of unread messages yourself (polling)
These methods require a knowledge of hardware dependent AT commands. If you want to understand/learn what's going on, give AT commands CMGR and CMGF a read
That said, the information you have explicitly asked for can be found in the function readSMS of gprs.cpp.
messageIndex is the index of selected memory where the message is stored.
*message is the buffer the message will be read into.
length is the length of bytes to be read.
The return status is always 0 (not a good strategy).
I would recommend distinguishing between read and unread messages using custom code. It depends upon your application

Socket Commuication with High frequency

I need to send data to another process every 0.02s.
The Server code:
//set socket, bind, listen
while(1){
sleep(0.02);
echo(newsockfd);
}
void echo (int sock)
{
int n;
char buffer[256]="abc";
n=send(sock,buffer,strlen(buffer),0);
if (n < 0) error("ERROR Sending");
}
The Client code:
//connect
while(1)
{
bzero(buffer,256);
n = read(sock,buffer,255);
printf("Recieved data:%s\n",buffer);
if (n < 0)
error("ERROR reading from socket");
}
The problem is that:
The client shows something like this:
Recieved data:abc
Recieved data:abcabcabc
Recieved data:abcabc
....
How does it happen? When I set sleep time:
...
sleep(2)
...
It would be ok:
Recieved data:abc
Recieved data:abc
Recieved data:abc
...
TCP sockets do not guarantee framing. When you send bytes over a TCP socket, those bytes will be received on the other end in the same order, but they will not necessarily be grouped the same way — they may be split up, or grouped together, or regrouped, in any way the operating system sees fit.
If you need framing, you will need to send some sort of packet header to indicate where each chunk of data starts and ends. This may take the form of either a delimiter (e.g, a \n or \0 to indicate where each chunk ends), or a length value (e.g, a number at the head of each chunk to denote how long it is).
Also, as other respondents have noted, sleep() takes an integer, so you're effectively not sleeping at all here.
sleep takes unsigned int as argument, so sleep(0.02) is actually sleep(0).
unsigned int sleep(unsigned int seconds);
Use usleep(20) instead. It will sleep in microseconds:
int usleep(useconds_t usec);
The OS is at liberty to buffer data (i.e. why not just send a full packet instead of multiple packets)
Besides sleep takes a unsigned integer.
The reason is that the OS is buffering data to be sent. It will buffer based on either size or time. In this case, you're not sending enough data, but you're sending it fast enough the OS is choosing to bulk it up before putting it on the wire.
When you add the sleep(2), that is long enough that the OS chooses to send a single "abc" before the next one comes in.
You need to understand that TCP is simply a byte stream. It has no concept of messages or sizes. You simply put bytes on the wire on one end and take them off on the other. If you want to do specific things, then you need to interpret the data special ways when you read it. Because of this, the correct solution is to create an actual protocol for this. That protocol could be as simple as "each 3 bytes is one message", or more complicated where you send a size prefix.
UDP may also be a good solution for you, depending on your other requirements.
sleep(0.02)
is effectively
sleep(0)
because argument is unsigned int, so implicit conversion does it for you. So you have no sleep at all here. You can use sleep(2) to sleep for 2 microseconds.Next, even if you had, there is no guarantee that your messages will be sent in a different frames. If you need this, you should apply some sort of delimiter, I have seen
'\0'
character in some implementation.
TCPIP stacks buffer up data until there's a decent amount of data, or until they decide that there's no more coming from the application and send what they've got anyway.
There are two things you will need to do. First, turn off Nagle's algorithm. Second, sort out some sort of framing mechanism.
Turning off Nagle's algorithm will cause the stack to "send data immediately", rather than waiting on the off chance that you'll be wanting to send more. It actually leads to less network efficiency because you're not filling up Ethernet frames, something to bare in mind on Gigabit where jumbo frames are required to get best throughput. But in your case timeliness is more important than throughput.
You can do your own framing by very simple means, eg by send an integer first that says how long the rest if the message will be. At the reader end you would read the integer, and then read that number of bytes. For the next message you'd send another integer saying how long that message is, etc.
That sort of thing is ok but not hugely robust. You could look at something like ASN.1 or Google Protocol buffers.
I've used Objective System's ASN.1 libraries and tools (they're not free) and they do a good job of looking after message integrity, framing, etc. They're good because they don't read data from a network connection one byte at a time so the efficiency and speed isn't too bad. Any extra data read is retained and included in the next message decode.
I've not used Google Protocol Buffers myself but it's possible that they have similar characteristics, and there maybe other similar serialisation mechanisms out there. I'd recommend avoiding XML serialisation for speed/efficiency reasons.