Sending TCP and UDP Data

Top  Previous  Next

In the previous sections, we have explained how to handle an incoming stream of data. You could say it was incoming-data driven. Sometimes you need just the opposite — you need to perform operations based on the sending of data.

Sending data with on_sock_data_sent event

Supposing that in a certain system, you need to send out a long string of data when a button is pressed. A simple code for this would look like this:

 

 

sub on_button_pressed

 sock.setdata("This is a long string waiting to be sent. Send me already!")

 sock.send

end sub

 

 

The code above would work, but only if at the moment of code execution the necessary amount of free space was available in the TX buffer (otherwise the data would get truncated). So, obviously, you need to make sure that the TX buffer has the necessary amount of free space before sending. A simple polling solution would look like this:

 

 

sub on_button_pressed

 dim s as string

 s = "This is a long string waiting to be sent. Send me already!"

 while sock.txfree < len(s)

 wend

 sock.setdata(s)

 sock.send

end sub

 

 

Again, this is not so good, as it would block other event handlers. So, instead of doing that, we would employ a code that uses on_sock_data_sent:

 

 

dim s as string

s = "This is a long string waiting to be sent. Send me already!"

 

sub on_button_pressed

 sock.notifysent(sock.txbuffsize-len(s)) ' causes the on_sock_data_sent event to fire when the TX buffer has space for our string

end sub

 

sub on_sock_data_sent

 sock.setdata(s) ' put data in TX buffer

 sock.send ' start sending it.

end sub

 

 

When we press the button, on_button_pressed event is generated, so now the system knows we have a string to send. Using sock.notifysent we make the system fire the on_ser_data_sent event when the necessary amount of free space becomes available. This event will only be fired once — and will be fired immediately if there is already enough available space.

Within the event handler for this event, we put the data in the TX buffer and start sending it.

 

note_warning-wt

Amount of data that will trigger on_sock_data_sent does not include uncommitted data in the TX buffer.

UDP datagrams are generated as you create them

In Using Buffers in TCP Mode we have already explained that for UDP you have a complete control over how the data you are sending is divided into the UDP datagrams. Each time you use the sock.send method you draw the boundary between the datagrams- the previous one is "closed" and the new one "begins". You can even send out an empty UDP datagram by executing sock.send without using the sock.setdata first.

Correctly responding to the sender of each UDP datagram

With UDP, your socket may be receiving UDP datagrams from several different hosts. When the on_sock_data_arrival event handler is entered (see Receiving Data in UDP mode) the following properties automatically reflect the source of the current datagram- sock.remotemac, sock.remoteip, and sock.remoteport. Additionally, the sock.bcast property will tell you whether the datagram was a regular or a broadcast one (this material has already been covered in Checking Connection Status).

Additionally, any datagram that was generated and sent from within the on_sock_data_arrival event handler will be send to the sender of the datagram for processing of which the on_sock_data_arrival event handler was entered.

The point is that if you are sending out a datagram from within the on_sock_data_arrival event handler you are automatically replying to the sender of the datagram being processed. The following example sends back "GOT DATAGRAM FROM xxx.xxx.xxx.xxx" string in response to any datagram received by the socket:

 

 

sub on_sock_data_arrival

 sock.setdata("GOT DATAGRAM FROM " + sock.remoteip)

 sock.send

end sub

 

 

For the above example, even if several hosts send the datagrams to the socket at the same time each one of these hosts will get a correct reply back!

Now consider this example: each time the button is pressed the same message is generated:

 

 

sub on_button_pressed

 sock.setdata("GOT DATAGRAM FROM " + sock.remoteip)

 sock.send

end sub

 

 

The difference is that when you press the button the datagram will be sent to the destination, from which the most recent incoming UDP datagram was received (and accepted) by the socket!