{"id":1439,"date":"2016-12-14T12:52:07","date_gmt":"2016-12-14T12:52:07","guid":{"rendered":"https:\/\/ibex.tech\/visualcpp\/?p=1439"},"modified":"2022-02-17T06:24:02","modified_gmt":"2022-02-17T06:24:02","slug":"transmit-lots-of-packets","status":"publish","type":"post","link":"https:\/\/ibex.tech\/visualcpp\/tcp-ip\/transmit-lots-of-packets","title":{"rendered":"Transmit lots of packets"},"content":{"rendered":"<p>\nIf you don&#39;t have your socket set to non blocking (which means you have to deal with recv() wanting to block when you call it) then using the send() transmitfunction is no problem&nbsp;as it will block until the packet you are sending has gone out. &nbsp;However if you have O_NONBLOCK non blocking turned on so you can poll using recv() then you have a problem when sending say a large file. &nbsp;The send function will return the number of bytes it managed to send and you can use this to retry sending the remaining bytes, adding a delay to let the system catch up, but in our tests even adding in a 1000mS delay when this occurred we&#39;d still get the send() function ultimately&nbsp;returning&nbsp;a -1 error before all of the data had been sent. &nbsp;One fix to this may be to use a different function to wait for the socket to become free again but an easier fix is just to temporarily turn blocking mode back on when you do the transmit.\n<\/p>\n<h5>\nTurn socket blocking mode on and off<br \/>\n<\/h5>\n<pre>\r\n<code>\r\n\t\/\/Set blocking to on\r\n\tconst int flags = fcntl(tcp_server_client_socket, F_GETFL, 0);\r\n\tfcntl(tcp_server_client_socket, F_SETFL, (flags &amp; ~O_NONBLOCK));\r\n<\/code><\/pre>\n<pre>\r\n<code>\r\n\t\/\/Turn off blocking again\r\n\tconst int flags2 = fcntl(tcp_server_client_socket, F_GETFL, 0);\r\n\tfcntl(tcp_server_client_socket, F_SETFL, (flags2 | O_NONBLOCK));\r\n<\/code><\/pre>\n<p>\n&nbsp;\n<\/p>\n<h5>\nAn example with a complete transmit handler<br \/>\n<\/h5>\n<pre>\r\n<code>\r\n\tfile_next_byte = 0;\r\n\tfile1 = fopen(filename_lea.c_str(), &quot;rb&quot;);\r\n\tif (file1)\r\n\t{\r\n\t\twhile (file_next_byte &lt; (filesize - 4))\t\t\/\/-2 checksum bytes that are already included in filesize\r\n\t\t{\r\n\t\t\t\/\/How many bytes to send in the next block?\r\n\t\t\tif (((filesize - 4) - file_next_byte) &gt; 1024)\r\n\t\t\t\tbytes_to_read = 1024;\r\n\t\t\telse\r\n\t\t\t\tbytes_to_read = ((filesize - 4) - file_next_byte);\r\n\r\n\t\t\tfile_next_byte += bytes_to_read;\r\n\r\n\t\t\t\/\/Read the bytes to a local buffer\r\n\t\t\tfread(&amp;file_data[0], sizeof(unsigned char), bytes_to_read, file1);\r\n\r\n\t\t\t\/\/Add the bytes to the checksum\r\n\t\t\tfor (count = 0; count &lt; bytes_to_read; count++)\r\n\t\t\t\tchecksum += file_data[count];\r\n\r\n\t\t\t\/\/Send the bytes \r\n\r\n\t\t\t\/\/Set blocking to on\r\n\t\t\tconst int flags = fcntl(tcp_server_client_socket, F_GETFL, 0);\r\n\t\t\tfcntl(tcp_server_client_socket, F_SETFL, (flags &amp; ~O_NONBLOCK));\r\n\r\n\r\n\t\t\tbytes_sent_count = 0;\r\n\t\t\twhile (bytes_sent_count &lt; bytes_to_read)\t\t\/\/Keep trying until it is sent\r\n\t\t\t{\r\n\t\t\t\tbytes_sent = send(tcp_server_client_socket, (char*)&amp;file_data[bytes_sent_count], (bytes_to_read - bytes_sent_count), 0);\r\n\t\t\t\tif (bytes_sent &lt; bytes_to_read)\r\n\t\t\t\t{\r\n\t\t\t\t\t\/\/delayMicroseconds(1000);\t\t\/\/If blocking wasn&#39;t turned on then this will happen for large files and in tests using a delay isn&#39;t enough to stop a -1 error to ultimately get returned.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\/\/With blocking turned on we don&#39;t get here in practice\r\n\t\t\t\t}\r\n\t\t\t\tif (bytes_sent &lt; 0)\t\t\/\/ -1 = error\r\n\t\t\t\t\tbreak;\r\n\t\t\t\tbytes_sent_count += bytes_sent;\r\n\t\t\t}\r\n\t\t}\r\n\t\tfclose(file1);\r\n\t\tfile1 = NULL;\r\n\r\n\t\t\/\/Turn off blocking again\r\n\t\tconst int flags2 = fcntl(tcp_server_client_socket, F_GETFL, 0);\r\n\t\tfcntl(tcp_server_client_socket, F_SETFL, (flags2 | O_NONBLOCK));\r\n<\/code><\/pre>\n<p>\n&nbsp;\n<\/p>\n<p>\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you don&#39;t have your socket set to non blocking (which means you have to deal with recv() wanting to block when you call it) then using the send() transmitfunction is no problem&nbsp;as it will block until the packet you are sending has gone out. &nbsp;However if you have O_NONBLOCK non blocking turned on so [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"class_list":["post-1439","post","type-post","status-publish","format-standard","hentry","category-tcp-ip"],"_links":{"self":[{"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/posts\/1439","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/comments?post=1439"}],"version-history":[{"count":3,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/posts\/1439\/revisions"}],"predecessor-version":[{"id":1442,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/posts\/1439\/revisions\/1442"}],"wp:attachment":[{"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/media?parent=1439"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/categories?post=1439"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ibex.tech\/visualcpp\/wp-json\/wp\/v2\/tags?post=1439"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}