{"id":6321,"date":"2024-04-06T00:01:19","date_gmt":"2024-04-06T07:01:19","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=6321"},"modified":"2024-04-13T09:12:32","modified_gmt":"2024-04-13T16:12:32","slug":"reading-the-keyboard-queue-ala-networking","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=6321","title":{"rendered":"Reading the Keyboard Queue ala Networking"},"content":{"rendered":"<p>A network program monitors one or more file descriptors (such as sockets) for activity. It reacts when information is ready to process. This technique can also be applied to keyboard input, though not as elegantly as the <em>kbhit()<\/em> function shown in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6305\">last week&#8217;s Lesson<\/a>.<br \/>\n<!--more--><br \/>\nNetworking programming is a complex booger of a topic, primarily because the code deals with multiple input and output sources as once. Each connection is monitored for activity in an endless loop. When activity is detected on one of the sources, the program acts.<\/p>\n<p>One way to monitor the several network connections is to use the <em>select()<\/em> function and its associated macros. This function scans a set of file descriptors for activity, then reports which one is active and ready for reading or writing.<\/p>\n<p>The details for using the <em>select()<\/em> function are complicated, so I&#8217;m not going to dive too deep here. To recreate last week&#8217;s program, I used three of the function&#8217;s macros: <code>FD_ZERO<\/code>, <code>FD_SET<\/code>, and <code>FD_ISSET<\/code>. These macros work on an <em>fd_set<\/em> structure that builds a collection of file descriptors that the <em>select()<\/em> function monitors.<\/p>\n<p>The <em>select()<\/em> function returns a value based on activity in the file descriptor set. When the return value isn&#8217;t zero, it means one of the file descriptors is ready for action, reading or writing.<\/p>\n<p>Here is an update to the code presented last week using the <em>select()<\/em> function and its macros to check for keyboard activity:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2024_04_06-Lesson.c\" rel=\"noopener\" target=\"_blank\">2024_04_06-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;sys\/time.h&gt;\r\n#include &lt;sys\/select.h&gt;\r\n\r\nint main()\r\n{\r\n    char a;\r\n    fd_set keyread;\r\n    struct timeval timeout;\r\n    int r;\r\n\r\n    <span class=\"comments\">\/* preset values *\/<\/span>\r\n    a = 'A';\r\n    timeout.tv_sec = 0;        <span class=\"comments\">\/* timeout structure *\/<\/span>\r\n    timeout.tv_usec = 0;\r\n\r\n    <span class=\"comments\">\/* loop until keyboard input available *\/<\/span>\r\n    while(1)\r\n    {\r\n        <span class=\"comments\">\/* initailize file descriptor set *\/<\/span>\r\n        FD_ZERO(&amp;keyread);\r\n        FD_SET(0,&amp;keyread);\r\n        <span class=\"comments\">\/* check standard input status *\/<\/span>\r\n        r = select(1,&amp;keyread,NULL,NULL,&amp;timeout);\r\n        if( r==-1 )\r\n        {\r\n            perror(\"select\");\r\n            return 1;\r\n        }\r\n\r\n        <span class=\"comments\">\/* output the alphabet loop *\/<\/span>\r\n        printf(\" %c\",a++);\r\n        if( a=='Z' )\r\n            a = 'A';\r\n        <span class=\"comments\">\/* terminate on keyboard input *\/<\/span>\r\n        if( r&gt;0 )\r\n        {\r\n            <span class=\"comments\">\/* confirm that it's standard input *\/<\/span>\r\n            if( FD_ISSET(0,&amp;keyread) )\r\n            {\r\n                getchar();\r\n                break;\r\n            }\r\n        }\r\n    }\r\n\r\n    return 0;\r\n}<\/pre>\n<p>Before the <em>while<\/em> loop begins, a timeout structure is filled. The timeout is set to zero. (Refer to <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5862\">this post<\/a> for details about this structure.) This structure is referenced in the <em>select()<\/em> function call.<\/p>\n<p>Within the <em>while<\/em> loop, <em>fd_set<\/em> variable <code>keyread<\/code> is zeroed with the <code>FD_ZERO<\/code> macro. The <code>FD_SET<\/code> macro adds the standard input device (zero) to the set:<\/p>\n<p><code>FD_ZERO(&amp;keyread);<br \/>\nFD_SET(0,&amp;keyread);<\/code><\/p>\n<p>The <em>select()<\/em> statement configures the file descriptor set <code>keyread<\/code> for action:<\/p>\n<p><code>r = select(1,&amp;keyread,NULL,NULL,&amp;timeout);<\/code><\/p>\n<p>Immediately, a test is performed for an error, <code>if( r==-1 )<\/code>. When true, the program quits. Otherwise, an alphabet character is output in the endless <em>while<\/em> loop. This output shows the program stays busy as it monitors standard input.<\/p>\n<p>Next, the return value from <em>select()<\/em>, <code>r<\/code>, is compared with zero: <code>if( r&gt;0 )<\/code>. If true, the <code>FD_ISSET<\/code> macro tests standard input to see whether something is waiting to be read: <code>if( FD_ISSET(0,&amp;keyread))<\/code> When TRUE, input is available, and the loop terminates. The program ends.<\/p>\n<p>For output, the program spews forth the alphabet repeatedly until you press the Enter key. Yes, unlike last week&#8217;s example with the <em>kbhit()<\/em> function, the input buffer is released only when you press Enter.<\/p>\n<p>Granted, this technique wouldn&#8217;t be my first choice to check the keyboard for input. It does monitor standard input, and the loop continues during the monitoring, but it&#8217;s not the same as checking to see whether a single character is waiting to be read.<\/p>\n<p>For <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6345\">next week&#8217;s Lesson<\/a> I update this code with the <em>epoll()<\/em> family of functions.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You can use the networking function <em>select()<\/em> to check for pending keyboard input. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=6321\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-6321","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6321","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=6321"}],"version-history":[{"count":7,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6321\/revisions"}],"predecessor-version":[{"id":6364,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/6321\/revisions\/6364"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=6321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=6321"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=6321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}