<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=48&amp;t=8190&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2014-08-20T10:22:42+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=48&amp;t=8190&amp;mode</id>
<entry>
<author><name><![CDATA[Atlantis]]></name></author>
<updated>2014-08-20T10:22:42+01:00</updated>
<published>2014-08-20T10:22:42+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92134#p92134</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92134#p92134"/>
<title type="html"><![CDATA[Re: TCP - odbieranie całej wiadomości przez recv()]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92134#p92134"><![CDATA[
W porządku, już sprawdziłem. Tak jak podejrzewałem - informacja jest przekazywana.<br />Czyli to chyba faktycznie najlepszy sposób na przekazywanie większej ilości danych &quot;w dół&quot;, do kolejnych funkcji.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2174">Atlantis</a> — 20 sie 2014, o 10:22</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[charsz]]></name></author>
<updated>2014-08-20T08:58:48+01:00</updated>
<published>2014-08-20T08:58:48+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92124#p92124</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92124#p92124"/>
<title type="html"><![CDATA[Re: TCP - odbieranie całej wiadomości przez recv()]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92124#p92124"><![CDATA[
Odpowiedz jest prosta i w wynika z pierwszego pytania, a jesli nie widzisz jej to w 5 minut to sobie sprawdzisz.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=926">charsz</a> — 20 sie 2014, o 08:58</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Atlantis]]></name></author>
<updated>2014-08-20T08:07:30+01:00</updated>
<published>2014-08-20T08:07:30+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92123#p92123</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92123#p92123"/>
<title type="html"><![CDATA[Re: TCP - odbieranie całej wiadomości przez recv()]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92123#p92123"><![CDATA[
<div class="quotetitle">mokrowski napisał(a):</div><div class="quotecontent"><br />Przy przesyłaniu wskaźnika do funkcji, nie jest przesyłana informacja o wielkości bufora/tablicy na którą on ew. wskazuje. Typ traci informację o wielkości danych. A że wskaźnik jest na adres 32-bitowy, to i wielkość jest 4 bajty. Poza tym sizeof() to operator.<br /></div><br /><br />Oczywiście masz rację, przepraszam za zamieszanie.<br />Chciałbym przy tej okazji zapytać o jedno. Czy informacja o wielkości jest też tracona w przypadku przekazywania tablicy wchodzącej w skład struktury przez wskaźnik na tą strukturę. Czy konstrukcja sizeof(wskaźnik_na_strukture-&gt;tablica) zwróci prawidłową wartość?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2174">Atlantis</a> — 20 sie 2014, o 08:07</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Atlantis]]></name></author>
<updated>2014-08-19T21:08:58+01:00</updated>
<published>2014-08-19T21:08:58+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92077#p92077</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92077#p92077"/>
<title type="html"><![CDATA[Re: TCP - odbieranie całej wiadomości przez recv()]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92077#p92077"><![CDATA[
<div class="quotetitle">gordo napisał(a):</div><div class="quotecontent"><br /><div class="quotetitle">Atlantis napisał(a):</div><div class="quotecontent"> <strong>zamiast całej wiadomości (jak przedtem) recv() odbiera tylko po kilka znaków.</strong> Ktoś wie, dlaczego tak się dzieje?<br /></div><br /><br />rc = recv(sd, ans, sizeof(ans), MSG_WAITALL);<br /><br />Zdaje się, że w tym przypadku sizeof(ans) == 4.</div><br /><br /><br />Hmm... Z czego to wynika? Bo wydawało mi się, że do funkcji przekazałem bufor, który miał jakieś 1000 znaków pojemności...<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2174">Atlantis</a> — 19 sie 2014, o 21:08</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[gordo]]></name></author>
<updated>2014-08-19T20:27:50+01:00</updated>
<published>2014-08-19T20:27:50+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92073#p92073</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92073#p92073"/>
<title type="html"><![CDATA[Re: TCP - odbieranie całej wiadomości przez recv()]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92073#p92073"><![CDATA[
<div class="quotetitle">Atlantis napisał(a):</div><div class="quotecontent"><br /><strong>zamiast całej wiadomości (jak przedtem) recv() odbiera tylko po kilka znaków.</strong> Ktoś wie, dlaczego tak się dzieje?<br /></div><br /><br />rc = recv(sd, ans, sizeof(ans), MSG_WAITALL);<br /><br />Zdaje się, że w tym przypadku sizeof(ans) == 4.<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2592">gordo</a> — 19 sie 2014, o 20:27</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[Atlantis]]></name></author>
<updated>2014-08-19T18:44:16+01:00</updated>
<published>2014-08-19T18:44:16+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92058#p92058</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92058#p92058"/>
<title type="html"><![CDATA[TCP - odbieranie całej wiadomości przez recv()]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=8190&amp;p=92058#p92058"><![CDATA[
Eksperymentując z językiem C pod Linuksem natknąłem się na kolejny problem.<br />Mianowicie napisałem prostą aplikację, która łączy się z serwerem MPD (daemon pełniący funkcję odtwarzacza muzycznego), parsuje dane i wyświetla informacje o muzyce na wyświetlaczu 2x16 (korzystając z biblioteki wiringPi). Cały kod jest tutaj:<br /><br />[syntax=c]#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;sys/socket.h&gt;<br />#include &lt;netinet/in.h&gt;<br />#include &lt;arpa/inet.h&gt;<br />#include &lt;netdb.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;errno.h&gt;<br />#include &lt;time.h&gt;<br />#include &lt;signal.h&gt;<br />#include &lt;wiringPi.h&gt;<br /><br /><br /><br /><br />typedef struct {<br />char polecenie&#91;10&#93;;<br />void (* service)(char * params);<br />} cmd_t;<br /><br /><br />typedef struct {<br />char artist&#91;255&#93;;<br />char title&#91;255&#93;;<br />char album&#91;255&#93;;<br />char genre&#91;255&#93;;<br />char track&#91;50&#93;;<br />char filename&#91;500&#93;;<br /><br />uint16_t songid;<br />uint8_t volume;<br />uint8_t repeat;<br />uint8_t random;<br /><br />// enum state {STOP, PLAY, PAUSE};<br /><br />uint8_t newsong:1;<br />uint8_t updatevolume:1;<br />uint8_t updateartist:1;<br />uint8_t updatetitle:1;<br />uint8_t updatefilename:1;<br />} player_t;<br /><br /><br /><br /><br />void ScrollText (char *text);<br />void ScrollUpdateLoop (void);<br />void exit_program (int signum);<br />void parse_mpd (char *pBuf);<br />void parse_title (char *params);<br />void parse_artist (char *params);<br />void parse_album (char *params);<br />void parse_genre (char *params);<br />void parse_track (char *params);<br />void parse_filename (char *params);<br />void parse_songid (char *params);<br />void parse_volume (char *params);<br /><br /><br /><br /><br /><br />#define ILOSC_KOMEND_PODSTAWOWYCH 2<br /><br />int8_t cmd_index = 0;<br /><br />const char *commands&#91;&#93; = {<br />&quot;currentsong\n&quot;, <br />&quot;status\n&quot;,<br />&quot;stats\n&quot;, <br />&quot;play\n&quot;, <br />&quot;pause\n&quot;, <br />&quot;stop\n&quot;, <br />&quot;previous\n&quot;, <br />&quot;next\n&quot; };<br /><br /><br /><br />#define ANS_QTY 8<br /><br />const cmd_t answers&#91;ANS_QTY&#93; = {<br />// {answer}.{wskaźnik do funkcji},<br />{&quot;Title&quot;,parse_title},<br />{&quot;Artist&quot;,parse_artist},<br />{&quot;Album&quot;,parse_album},<br />{&quot;Genre&quot;,parse_genre},<br />{&quot;Track&quot;,parse_track},<br />{&quot;Id&quot;,parse_songid},<br />{&quot;volume&quot;,parse_volume},<br />{&quot;file&quot;,parse_filename}<br /><br />};<br /><br /><br />player_t player;<br /><br /><br />#define BufferLength 4000<br /><br /><br /><br />#define SERVER &quot;localhost&quot;<br /><br /><br />#define SERVPORT 6600<br /><br /><br />int sd;<br /><br />/* Zmienne i definicje do obsługi wyświetlacza */<br /><br />#define LCD_ROWS 2<br />#define LCD_COLS 16<br />#define LCD_BITS 4//4 or 8<br />#define LCD_RS 7<br />#define LCD_E 8<br />#define LCD_D0 17<br />#define LCD_D1 18<br />#define LCD_D2 27<br />#define LCD_D3 22<br />#define LCD_SCROLL_BUFFER_SIZE 2000<br />#define SCROLL_UPDATE_INTERVAL 500<br /><br />int handle;<br />char * beg_wsk;<br />char * lcd_wsk;<br />char * text_to_scroll;<br />uint32_t lcd_last_update;<br /><br />char lcd_scroll_buffer&#91;LCD_SCROLL_BUFFER_SIZE&#93;;<br /><br /><br /><br /><br /><br /><br /><br />void exit_program (int signum) {<br /><br />close (sd);<br />printf(&quot;\nProgram terminated, exit code %i\n&quot;, signum);<br />lcdClear(handle);<br />exit (1);<br />}<br /><br /><br />int main(int argc, char *argv&#91;&#93;) {<br /><br />/* Variable and structure definitions. */<br /><br />int rc, length = sizeof(int);<br />struct sockaddr_in serveraddr;<br />char buffer&#91;BufferLength&#93;;<br />char server&#91;255&#93;;<br />char temp;<br />int totalcnt = 0;<br />struct hostent *hostp;<br />int comm_timer = 0;<br /><br /><br /><br /><br /><br />/* Demonizacja */<br /><br /><br />/* Our process ID and Session ID */<br />        pid_t pid, sid;<br />        <br />        /* Fork off the parent process */<br />        pid = fork();<br />        if (pid &lt; 0) {<br />                exit(EXIT_FAILURE);<br />        }<br />        /* If we got a good PID, then<br />           we can exit the parent process. */<br />        if (pid &gt; 0) {<br />                exit(EXIT_SUCCESS);<br />        }<br /><br />        /* Change the file mode mask */<br />        umask(0);<br />                <br />        /* Open any logs here */        <br />                <br />        /* Create a new SID for the child process */<br />        sid = setsid();<br />        if (sid &lt; 0) {<br />                /* Log the failure */<br />                exit(EXIT_FAILURE);<br />        }<br />        <br /><br />        <br />        /* Change the current working directory */<br />        if ((chdir(&quot;/&quot;)) &lt; 0) {<br />                /* Log the failure */<br />                exit(EXIT_FAILURE);<br />        }<br />        <br />        /* Close out the standard file descriptors */<br />        close(STDIN_FILENO);<br />        close(STDOUT_FILENO);<br />        close(STDERR_FILENO);<br /><br /><br /><br /><br /><br /><br /><br /><br />buffer&#91;BufferLength-1&#93; = '\0';<br />memset(&amp;player, 0x00, sizeof(player));<br /><br />player.newsong = 1;<br />player.updatevolume = 1;<br /><br /><br /><br />wiringPiSetupGpio();<br />lcdInit (LCD_ROWS, LCD_COLS, LCD_BITS, LCD_RS, LCD_E, LCD_D0, LCD_D1, LCD_D2, LCD_D3, 0, 0, 0, 0);<br /><br /><br />signal(SIGINT, exit_program);<br />signal(SIGKILL, exit_program);<br /><br />if ((sd = socket(AF_INET, SOCK_STREAM, 0)) &lt; 0) {<br />perror(&quot;Client-socket() error&quot;);<br />exit(-1);<br />}<br />    else printf(&quot;Client-socket() OK\n&quot;);<br /><br />    /*If the server hostname is supplied*/<br /><br />    if(argc &gt; 1) {<br /><br />/*Use the supplied argument*/<br /><br />strncpy(server, argv&#91;1&#93;, sizeof(server));<br />printf(&quot;Connecting to the MPD server at %s, port %d ...\n&quot;, server, SERVPORT);<br />    }<br />else<br />    /*Use the default server name or IP*/<br />strncpy(server, SERVER, sizeof(server));<br /><br />memset(&amp;serveraddr, 0x00, sizeof(struct sockaddr_in));<br />serveraddr.sin_family = AF_INET;<br />serveraddr.sin_port = htons(SERVPORT);<br /><br />if ((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE) {<br /><br />/* When passing the host name of the server as a */<br />/* parameter to this program, use the gethostbyname() */<br />/* function to retrieve the address of the host server. */<br />/***************************************************/<br />/* get host address */<br /><br />hostp = gethostbyname(server);<br /><br />if(hostp == (struct hostent *)NULL) {<br /><br />printf(&quot;HOST NOT FOUND --&gt; &quot;);<br /><br />/* h_errno is usually defined */<br />/* in netdb.h */<br /><br />printf(&quot;h_errno = %d\n&quot;,h_errno);<br />printf(&quot;---This is a client program---\n&quot;);<br />printf(&quot;Command usage: %s &lt;server name or IP&gt;\n&quot;, argv&#91;0&#93;);<br />close(sd);<br />exit(-1);<br />}<br /><br />memcpy(&amp;serveraddr.sin_addr, hostp-&gt;h_addr, sizeof(serveraddr.sin_addr));<br />    }<br /><br />/* After the socket descriptor is received, the */<br />/* connect() function is used to establish a */<br />/* connection to the server. */<br />/***********************************************/<br />/* connect() to server. */<br /><br />if((rc = connect(sd, (struct sockaddr *)&amp;serveraddr, sizeof(serveraddr))) &lt; 0) {<br />perror(&quot;Client-connect() error&quot;);<br />close(sd);<br />exit(-1);<br />}<br />else printf(&quot;Connection established...\n&quot;);<br /><br />/* Flushing buffer */<br />rc = recv(sd, buffer, (sizeof(buffer)-1), 0);<br /><br /><br /><br />while (1) {<br /><br />/*Zdarzenie obsługi transmisji, wykonywane co 300 milisekund*/<br /><br />if (millis() &gt; comm_timer + 300) {<br /><br />rc = send(sd, commands&#91;cmd_index&#93;, strlen(commands&#91;cmd_index&#93;), 0); <br /><br />if(rc &lt; 0) {<br />perror(&quot;Client-write() error&quot;);<br />rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &amp;temp, &amp;length);<br />if(rc == 0) {<br />/* Print out the asynchronously received error. */<br />errno = temp;<br />perror(&quot;SO_ERROR was&quot;);<br />}<br />close(sd);<br />exit(-1);<br />}<br /><br /><br />rc = recv(sd, buffer, (sizeof(buffer)-1), 0);<br /><br />if (rc &gt; 0) {<br />buffer&#91;rc&#93; = '\0';<br />parse_mpd(buffer);<br />}<br /><br /><br />/* Sprawdzamy czy zmieniła się piosenka, jeśli tak<br />trzeba będzie uaktualnić info na wyświetlaczu */<br />if (player.newsong) {<br />/*Czy uaktualniono info o tytule?*/<br />if (player.updatetitle &amp;&amp; player.updateartist) {<br />sprintf(lcd_scroll_buffer, &quot;%s -%s        &quot;, player.artist, player.title);<br />}<br />else if (player.updatetitle &amp;&amp; !player.updateartist) {<br />sprintf(lcd_scroll_buffer, &quot;Unknown artist -%s        &quot;, player.title);<br />}<br />else if (!player.updatetitle &amp;&amp; player.updateartist) {<br />sprintf(lcd_scroll_buffer, &quot;%s - Unknown song        &quot;, player.artist);<br />}<br />else if (player.updatefilename) {<br />sprintf(lcd_scroll_buffer, &quot;file:%s        &quot;, player.filename);<br />}<br />else {<br />sprintf(lcd_scroll_buffer, &quot;ERROR: No metadata for this song        &quot;);<br />}<br /><br />ScrollText(lcd_scroll_buffer);<br /><br />player.newsong = 0;<br />player.updateartist = 0;<br />player.updatetitle = 0;<br />player.updatefilename = 0;<br />}<br /><br /><br />/* Sprawdzamy czy zmieniła się glośność, jeśli tak<br />trzeba będzie uaktualnić info na wyświetlaczu */<br />if (player.updatevolume) {<br />lcdPosition(handle, 8, 1);<br />lcdPuts(handle, &quot;    &quot;);<br />lcdPosition(handle, 0, 1);<br />lcdPrintf(handle, &quot;Volume: %i&quot;, player.volume);<br /><br />player.updatevolume = 0;<br />}<br /><br /><br /><br />if (cmd_index &lt; ILOSC_KOMEND_PODSTAWOWYCH) {<br />cmd_index++;<br />}<br />else {<br />cmd_index = 0;<br />}<br /><br />comm_timer = millis();<br /><br />}<br /><br />/* Zdarzenie obsługi przewijania na wyświetlaczu */<br />ScrollUpdateLoop();<br /><br /><br />usleep(500000);<br />}<br /><br />close(sd);<br />exit(EXIT_SUCCESS);<br />return 0;<br />}<br /><br /><br />void parse_mpd (char *pBuf) {<br /><br />char *line;<br />char *restofbuffer;<br />char *cmd;<br />char *restofline;<br /><br />int i;<br /><br />line = strtok_r(pBuf, &quot;\n&quot;, &amp;restofbuffer);<br /><br />while (line != NULL) {<br /><br />cmd = strtok_r(line, &quot;: &quot;, &amp;restofline);<br /><br />for (i=0; i&lt; ANS_QTY; i++) {<br />if (strncasecmp(cmd, answers&#91;i&#93;.polecenie, strlen(cmd)) == 0) {<br />answers&#91;i&#93;.service (restofline);<br />break;<br />}<br />}<br /><br />line = strtok_r(NULL, &quot;\n&quot;, &amp;restofbuffer);<br /><br />}<br /><br />}<br /><br /><br /><br />void ScrollText (char *text) {<br /><br />text_to_scroll = beg_wsk = lcd_wsk = text;<br /><br />}<br /><br /><br />void ScrollUpdateLoop (void) {<br />uint8_t i;<br />if (millis() &gt; (lcd_last_update + SCROLL_UPDATE_INTERVAL)) {<br />lcd_last_update = millis();<br />lcd_wsk = beg_wsk;<br />lcdPosition(handle, 0, 0);<br />for (i=0; i &lt; LCD_COLS; i++) {<br />lcdPutchar(handle, *lcd_wsk);<br />lcd_wsk++;<br />if (!(*lcd_wsk)) lcd_wsk = text_to_scroll;<br />}<br />beg_wsk++;<br />if (!(*beg_wsk)) beg_wsk = text_to_scroll;<br />}<br />}<br /><br /><br /><br />void parse_title (char *params) {<br />if (strncasecmp (params, player.title, strlen(params)) != 0) {<br />player.updatetitle = 1;<br />strncpy(player.title, params, sizeof(player.title));<br />}<br />}<br /><br /><br />void parse_artist (char *params) {<br />if (strncasecmp(params, player.artist, strlen(params)) != 0) {<br />player.updateartist = 1;<br />strncpy(player.artist, params, sizeof(player.artist));<br />}<br />}<br /><br /><br />void parse_album (char *params) {<br />strncpy(player.album, params, sizeof(player.album));<br />}<br /><br /><br />void parse_genre (char *params) {<br />strncpy(player.genre, params, sizeof(player.genre));<br />}<br /><br /><br />void parse_track (char *params) {<br />strncpy(player.track, params, sizeof(player.track));<br />}<br /><br /><br />void parse_filename (char *params) {<br />if (strncasecmp(params, player.filename, strlen(params)) != 0) {<br />player.updatefilename = 1;<br />strncpy(player.filename, params, sizeof(player.filename));<br />}<br />}<br /><br /><br />void parse_songid (char *params) {<br /><br />uint16_t id  = atoi(params);<br /><br />if (id != player.songid) {<br />player.newsong = 1;<br />player.songid = id;<br />}<br />}<br /><br /><br />void parse_volume (char *params) {<br /><br />uint8_t vol  = atoi(params);<br />if ((vol &gt;= 0) &amp;&amp; (vol &lt;= 100)) {<br />if (vol != player.volume) {<br />player.updatevolume = 1;<br />player.volume = vol;<br />}<br />}<br />}[/syntax]<br /><br />Właściwie funkcje parsujące i wyświetlające są nieważne. Najważniejsze jest to, co dzieje się na początku funkcji main() oraz w jej pętli głównej. Szczególnie ważny jest tutaj fakt, że <strong>funkcja recv() pobiera do bufora komplet danych odsyłanych przez serwer.</strong>.<br /><br />Dzisiaj postanowiłem trochę upiększyć kod, wydzielając funkcje odpowiedzialne za łączność z MPD do osobnej biblioteki. Tak oto powstały dwa pliki:<br /><br />mpdcl.h<br />[syntax=c]#ifndef MPDCL_H<br />#define MPDCL_H<br /><br />#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;sys/socket.h&gt;<br />#include &lt;netinet/in.h&gt;<br />#include &lt;arpa/inet.h&gt;<br />#include &lt;netdb.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;errno.h&gt;<br />#include &lt;time.h&gt;<br /><br />/* ERROR CODES */<br />#define _ERR_SOCKET -1<br />#define _ERR_HOST_NOT_FOUND -2<br />#define _ERR_CONNECT -3<br />#define _ERR_SEND -4<br />#define _ERR_RECV -5<br /><br /><br />typedef struct {<br />char artist&#91;255&#93;;<br />char title&#91;255&#93;;<br />char album&#91;255&#93;;<br />char genre&#91;255&#93;;<br />char track&#91;50&#93;;<br />char filename&#91;500&#93;;<br /><br />uint16_t songid;<br />uint8_t volume;<br />uint8_t repeat;<br />uint8_t random;<br /><br />// enum state {STOP, PLAY, PAUSE};<br /><br />uint8_t newsong:1;<br />uint8_t updatevolume:1;<br />uint8_t updateartist:1;<br />uint8_t updatetitle:1;<br />uint8_t updatefilename:1;<br />} player_t;<br /><br /><br />typedef struct {<br />char name&#91;10&#93;;<br />void (* service)(player_t *player, char * params);<br />} ans_t;<br /><br /><br />int mpd_connect (const char *address, const int port);<br />int mpd_send_cmd (const char *cmd, char *ans);<br />void mpd_disconnect (void);<br />int mpd_read_player_status (player_t *player);<br />void mpd_parse_player_status (player_t *player, char *pBuf);<br />void mpd_parse_title (player_t *player, char * params);<br />void mpd_parse_artist (player_t *player, char * params);<br />void mpd_parse_album (player_t *player, char * params);<br />void mpd_parse_genre (player_t *player, char * params);<br />void mpd_parse_track (player_t *player, char * params);<br />void mpd_parse_filename (player_t *player, char * params);<br />void mpd_parse_songid (player_t *player, char * params);<br />void mpd_parse_volume (player_t *player, char * params);<br /><br /><br />#endif[/syntax]<br /><br /><br />mpdcl.c<br />[syntax=c]#include &quot;mpdcl.h&quot;<br /><br />#define CMD_QTY 3<br /><br />const char *commands&#91;&#93; = {<br />&quot;currentsong\n&quot;, <br />&quot;status\n&quot;,<br />&quot;stats\n&quot;};<br /><br /><br />#define ANS_QTY 8<br /><br />const ans_t answers&#91;ANS_QTY&#93; = {<br />// {answer}.{wskaźnik do funkcji},<br />{&quot;Title&quot;,mpd_parse_title},<br />{&quot;Artist&quot;,mpd_parse_artist},<br />{&quot;Album&quot;,mpd_parse_album},<br />{&quot;Genre&quot;,mpd_parse_genre},<br />{&quot;Track&quot;,mpd_parse_track},<br />{&quot;Id&quot;,mpd_parse_songid},<br />{&quot;volume&quot;,mpd_parse_volume},<br />{&quot;file&quot;,mpd_parse_filename}<br /><br />};<br /><br /><br />int sd;<br />struct sockaddr_in serveraddr;<br />struct hostent *hostp;<br /><br /><br />int mpd_connect (const char *address, const int port) {<br /><br /><br />if ((sd = socket(AF_INET, SOCK_STREAM, 0)) &lt; 0) {<br />return _ERR_SOCKET;<br />}<br /><br />memset(&amp;serveraddr, 0x00, sizeof(struct sockaddr_in));<br />serveraddr.sin_family = AF_INET;<br />serveraddr.sin_port = htons(port);<br /><br />if ((serveraddr.sin_addr.s_addr = inet_addr(address)) == (unsigned long)INADDR_NONE) {<br /><br />hostp = gethostbyname(address);<br /><br />if(hostp == (struct hostent *)NULL) {<br />close(sd);<br />return _ERR_HOST_NOT_FOUND;<br />}<br /><br />memcpy(&amp;serveraddr.sin_addr, hostp-&gt;h_addr, sizeof(serveraddr.sin_addr));<br />}<br /><br />if((connect(sd, (struct sockaddr *)&amp;serveraddr, sizeof(serveraddr))) &lt; 0) {<br />close(sd);<br />return _ERR_CONNECT;<br />}<br /><br /><br />}<br /><br /><br /><br /><br />int mpd_send_cmd (const char *cmd, char *ans) {<br /><br />int rc;<br /><br /><br />rc = send(sd, cmd, strlen(cmd), MSG_WAITALL);<br />if(rc &lt; 0) {<br />close(sd);<br />return _ERR_SEND;<br />}<br /><br /><br />rc = recv(sd, ans, sizeof(ans), MSG_WAITALL);<br />if (rc &gt; 0) {<br />ans&#91;rc&#93; = '\0';<br />}<br />else {<br />close(sd);<br />return _ERR_RECV;<br />}<br /><br />return 0;<br /><br />}<br /><br /><br />void mpd_disconnect (void) {<br /><br />close(sd);<br /><br />}<br /><br /><br />int mpd_read_player_status (player_t *player) {<br /><br />char buffer&#91;1000&#93;;<br />int i, rc;<br /><br />memset(buffer, 0x00, sizeof(buffer));<br /><br />for (i=0; i&lt;CMD_QTY; i++) {<br />rc = mpd_send_cmd(commands&#91;i&#93;, buffer);<br />if (rc &lt; 0) {<br />return rc;<br />}<br />else {<br />mpd_parse_player_status(player, buffer);<br />}<br />}<br /><br />return 0;<br /><br />}<br /><br /><br /><br />void mpd_parse_player_status (player_t *player, char *pBuf) {<br /><br />char *line;<br />char *restofbuffer;<br />char *cmd;<br />char *restofline;<br /><br />int i;<br /><br />line = strtok_r(pBuf, &quot;\n&quot;, &amp;restofbuffer);<br /><br />while (line != NULL) {<br /><br />cmd = strtok_r(line, &quot;: &quot;, &amp;restofline);<br /><br />for (i=0; i&lt; ANS_QTY; i++) {<br />if (strncasecmp(cmd, answers&#91;i&#93;.name, strlen(cmd)) == 0) {<br />answers&#91;i&#93;.service (player, restofline);<br />break;<br />}<br />}<br /><br />line = strtok_r(NULL, &quot;\n&quot;, &amp;restofbuffer);<br /><br />}<br /><br />}<br /><br /><br />void mpd_parse_title (player_t *player, char * params) {<br />if (strncasecmp (params, player-&gt;title, strlen(params)) != 0) {<br />player-&gt;updatetitle = 1;<br />strncpy(player-&gt;title, params, sizeof(player-&gt;title));<br />}<br />}<br /><br /><br />void mpd_parse_artist (player_t *player, char * params) {<br />if (strncasecmp(params, player-&gt;artist, strlen(params)) != 0) {<br />player-&gt;updateartist = 1;<br />strncpy(player-&gt;artist, params, sizeof(player-&gt;artist));<br />}<br />}<br /><br /><br />void mpd_parse_album (player_t *player, char * params) {<br />strncpy(player-&gt;album, params, sizeof(player-&gt;album));<br />}<br /><br /><br />void mpd_parse_genre (player_t *player, char * params) {<br />strncpy(player-&gt;genre, params, sizeof(player-&gt;genre));<br />}<br /><br /><br />void mpd_parse_track (player_t *player, char * params) {<br />strncpy(player-&gt;track, params, sizeof(player-&gt;track));<br />}<br /><br /><br />void mpd_parse_filename (player_t *player, char * params) {<br />if (strncasecmp(params, player-&gt;filename, strlen(params)) != 0) {<br />player-&gt;updatefilename = 1;<br />strncpy(player-&gt;filename, params, sizeof(player-&gt;filename));<br />}<br />}<br /><br /><br />void mpd_parse_songid (player_t *player, char * params) {<br /><br />uint16_t id  = atoi(params);<br /><br />if (id != player-&gt;songid) {<br />player-&gt;newsong = 1;<br />player-&gt;songid = id;<br />}<br />}<br /><br /><br />void mpd_parse_volume (player_t *player, char * params) {<br /><br />uint8_t vol  = atoi(params);<br />if ((vol &gt;= 0) &amp;&amp; (vol &lt;= 100)) {<br />if (vol != player-&gt;volume) {<br />player-&gt;updatevolume = 1;<br />player-&gt;volume = vol;<br />}<br />}<br />}[/syntax]<br /><br />No i jeszcze plik z głównym kodem programu:<br /><br />[syntax=c]#include &lt;stdio.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;time.h&gt;<br />#include &lt;signal.h&gt;<br />#include &lt;wiringPi.h&gt;<br /><br />#include &quot;mpdcl.h&quot;<br /><br /><br /><br />/* Zmienne i definicje do obsługi wyświetlacza */<br /><br />#define LCD_ROWS 2<br />#define LCD_COLS 16<br />#define LCD_BITS 4//4 or 8<br />#define LCD_RS 7<br />#define LCD_E 8<br />#define LCD_D0 17<br />#define LCD_D1 18<br />#define LCD_D2 27<br />#define LCD_D3 22<br />#define LCD_SCROLL_BUFFER_SIZE 2000<br />#define SCROLL_UPDATE_INTERVAL 500<br /><br />int handle;<br />char * beg_wsk;<br />char * lcd_wsk;<br />char * text_to_scroll;<br />uint32_t lcd_last_update;<br /><br />char lcd_scroll_buffer&#91;LCD_SCROLL_BUFFER_SIZE&#93;;<br /><br /><br /><br />void ScrollText (char *text);<br />void ScrollUpdateLoop (void);<br /><br /><br /><br />void exit_program (int signum) {<br /><br />mpd_disconnect();<br />lcdClear(handle);<br />exit (1);<br />}<br /><br /><br />int main(int argc, char *argv&#91;&#93;) {<br /><br /><br />/* Demonizacja */<br />/*<br />pid_t pid, sid;<br /><br />pid = fork();<br />if (pid &lt; 0) {<br />exit(EXIT_FAILURE);<br />}<br /><br />if (pid &gt; 0) {<br />exit(EXIT_SUCCESS);<br />}<br /><br /><br />umask(0);<br />    <br /><br />sid = setsid();<br />if (sid &lt; 0) {<br />exit(EXIT_FAILURE);<br />}<br />        <br /><br />        <br />if ((chdir(&quot;/&quot;)) &lt; 0) {<br />exit(EXIT_FAILURE);<br />}<br />        <br />close(STDIN_FILENO);<br />close(STDOUT_FILENO);<br />close(STDERR_FILENO);<br />*/<br /><br /><br />player_t player;<br /><br />int comm_timer = 0;<br />int rc;<br /><br />char buffer&#91;2000&#93;;<br />memset(buffer, 0x00, sizeof(buffer));<br /><br /><br />memset(&amp;player, 0x00, sizeof(player));<br />player.newsong = 1;<br />player.updateartist = 1;<br />player.updatetitle = 1;<br />player.updatefilename = 1;<br /><br /><br /><br />wiringPiSetupGpio();<br />lcdInit (LCD_ROWS, LCD_COLS, LCD_BITS, LCD_RS, LCD_E, LCD_D0, LCD_D1, LCD_D2, LCD_D3, 0, 0, 0, 0);<br /><br /><br />signal(SIGINT, exit_program);<br />signal(SIGKILL, exit_program);<br /><br />mpd_connect(&quot;localhost&quot;, 6600);<br /><br /><br />while (1) {<br /><br />/*Zdarzenie obsługi transmisji, wykonywane co 300 milisekund*/<br /><br />if (millis() &gt; comm_timer + 300) {<br /><br />rc = mpd_read_player_status(&amp;player);<br />printf(&quot;Error code of mpr_read_status() function was: %i\n&quot;, rc);<br /><br />printf(&quot;Artist: %s\nTitle: %s\nAlbum: %s\nFilename: %s\nVolume: %i\n&quot;, player.artist, player.title, player.album, player.filename, player.volume);<br />mpd_send_cmd(&quot;currentsong\n&quot;, buffer);<br />printf(&quot;Reply for currentsong: %s\n&quot;, buffer);<br /><br />/* Sprawdzamy czy zmieniła się piosenka, jeśli tak<br />trzeba będzie uaktualnić info na wyświetlaczu */<br />if (player.newsong) {<br />/*Czy uaktualniono info o tytule?*/<br />if (player.updatetitle &amp;&amp; player.updateartist) {<br />//sprintf(lcd_scroll_buffer, &quot;%s -%s        &quot;, player.artist, player.title);<br />}<br />else if (player.updatetitle &amp;&amp; !player.updateartist) {<br />sprintf(lcd_scroll_buffer, &quot;Unknown artist -%s        &quot;, player.title);<br />}<br />else if (!player.updatetitle &amp;&amp; player.updateartist) {<br />sprintf(lcd_scroll_buffer, &quot;%s - Unknown song        &quot;, player.artist);<br />}<br />else if (player.updatefilename) {<br />sprintf(lcd_scroll_buffer, &quot;file:%s        &quot;, player.filename);<br />}<br />else {<br />sprintf(lcd_scroll_buffer, &quot;ERROR: No metadata for this song        &quot;);<br />}<br /><br />ScrollText(lcd_scroll_buffer);<br /><br />player.newsong = 0;<br />player.updateartist = 0;<br />player.updatetitle = 0;<br />player.updatefilename = 0;<br />}<br /><br /><br />/* Sprawdzamy czy zmieniła się glośność, jeśli tak<br />trzeba będzie uaktualnić info na wyświetlaczu */<br />if (player.updatevolume) {<br />lcdPosition(handle, 8, 1);<br />lcdPuts(handle, &quot;    &quot;);<br />lcdPosition(handle, 0, 1);<br />lcdPrintf(handle, &quot;Volume: %i&quot;, player.volume);<br /><br />player.updatevolume = 0;<br />}<br /><br />comm_timer = millis();<br /><br />}<br /><br />/* Zdarzenie obsługi przewijania na wyświetlaczu */<br />ScrollUpdateLoop();<br /><br /><br />usleep(500000);<br />}<br /><br />mpd_disconnect();<br />exit(EXIT_SUCCESS);<br />return 0;<br />}<br /><br /><br /><br />void ScrollText (char *text) {<br /><br />text_to_scroll = beg_wsk = lcd_wsk = text;<br /><br />}<br /><br /><br />void ScrollUpdateLoop (void) {<br />uint8_t i;<br />if (millis() &gt; (lcd_last_update + SCROLL_UPDATE_INTERVAL)) {<br />lcd_last_update = millis();<br />lcd_wsk = beg_wsk;<br />lcdPosition(handle, 0, 0);<br />for (i=0; i &lt; LCD_COLS; i++) {<br />lcdPutchar(handle, *lcd_wsk);<br />lcd_wsk++;<br />if (!(*lcd_wsk)) lcd_wsk = text_to_scroll;<br />}<br />beg_wsk++;<br />if (!(*beg_wsk)) beg_wsk = text_to_scroll;<br />}<br />}[/syntax]<br /><br />Ta wersja programu nie chce działać jak należy. Po godzinie zabawy udało mi się znaleźć przycyznę - <strong>zamiast całej wiadomości (jak przedtem) recv() odbiera tylko po kilka znaków.</strong> Ktoś wie, dlaczego tak się dzieje? Ustawienie flag MSG_WAITALL w niczym nie pomaga. Można by pewnie próbować odbierać poszczególne fragmenty w pętli, łącząc je potem, zupełnie jak na AVR-ach. Jednak przede wszystkim interesuje mnie <strong>dlaczego</strong> kod przestał działać. Przecież nadając komunikat za pomocą TCP wysyłam również iformację o jego długości, więc druga strona powinna wiedzieć, czego się spodziewać. Przecież przedtem działało jak należy... Coś się mogło &quot;wyłączyć&quot;?<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=2174">Atlantis</a> — 19 sie 2014, o 18:44</p><hr />
]]></content>
</entry>
</feed>