Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze: TCP server - problém s komunikací

Aktivity
Avatar
švrčajs
Člen
Avatar
švrčajs:1.2.2016 21:08

Zdarec, řeším menší problém, mám model, který ovládám pomocí wifi a raspberry... Komunikuji pomocí TCP protokolu, kde server, který běží na raspberry je v c++ a klient, který běží na noťasu(win) je v c#. A teď můj problém, připojím se s klientem na server, zahájím ovládání modelu a vše funguje jak má, ovšem po cca 30 sekundách, záleží na tom, jak často měním pozici joysticku a taky na intervalu timeru, mi to nereaguje na poslané příkazy, kola se točí a cca po 3 sekundách se zastaví. Mám naprogramovanou i druhou verzi s UDP protokolem a tam to je bez problému, ale zase u UDP nepoznám, když se mi klient odpojí, což potřebuji poznat (model se vzdálí z dosahu wifi a nejde pak zastavit :D ) Je možné, aby raspberry (256mb ram) nestíhalo všechny náležitosti TCP protokolu ? :D případně, nemám něco blbě naprogramovaného ?

tady kód serveru

#include "PCA9685.h"
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include <stdlib.h>


int main(int argc , char *argv[])
{
    PCA9685 pwm;
    pwm.init(0,0x40);
    pwm.setPWMFreq (60);

    int socket_desc , client_sock , size , read_size;
    struct sockaddr_in server , client;
    char buffer[1000];

    socket_desc = socket(AF_INET , SOCK_STREAM , IPPROTO_TCP);
    if (socket_desc == -1)
    {
        //dodělat chybovou hlášku...(nelze vytvrořit socket)
    }
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(666);

    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
    {
        //dodělat chyb. hlás. nelze bindovat...
    }
    while(1)
    {
        listen(socket_desc , 1);
        size = sizeof(struct sockaddr_in);

        client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&size);
        if (client_sock < 0)
        {
            //selhal accept
            return 1;
        }

        while( (read_size = recv(client_sock , buffer , 1000 , 0)) > 0 )
        {

           pwm.setPWM(atoi(strtok(buffer, "-")), 0 , atoi(strtok(NULL, "-")));
           //kod....
           // write(client_sock , buffer , strlen(buffer));
        }

        if(read_size == 0 || read_size == -1 )
        {
           //klient odpojen, nastavit vše na nulovou pozici(směr, plyn)
           pwm.setPWM(4,0,375);
           pwm.setPWM(6,0,375);
        }
        close(client_sock);
   }
    return 0;
}

a klienta

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;

namespace KlientWF.Classes
{
    class Client
    {
        private Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        public bool MyConnect()
        {

            try
            {
                s.Connect(IPAddress.Parse("192.168.1.1"), 666);
                return true;
            }
            catch
            {
                return false;
            }


        }
        public bool MyDisconnect()
        {
            try
            {
                s.Disconnect(true);
                return true;
            }
            catch
            {
                return false;
            }

        }

        public void SendMessage(int channel, int position2)
        {
            byte[] message = Encoding.ASCII.GetBytes(channel.ToString() + "-"  + position2.ToString());
            s.Send(message);
        }

        public bool IsOnline()
        {
            return s.Connected;
        }
    }
}
 
Odpovědět
1.2.2016 21:08
Avatar
LacoS.
Člen
Avatar
LacoS.:8.4.2016 13:01

Ahoj.

Este sa s tym bavis?

  1. ... najprv by som si vytvoril aj server na PC, a z klienta v PC by som sa pripojil na oba servre a posielal by som rovnaky telegram do oboch serverov (len kvoli kontrole, ci neblbne nahodou klient...)
  2. ... TCP je dost zlozite (kontroluje sa spojenie atd, pri UPD je to jedno)

... moze sa stat, ze ak vysielas telegramy, so maju dlzku napr. 100 bajtov, tak niekedy ho moze poslat na viackrat (napr. 40+60 bajtov), takze na druhej strane ho musis "zlepit".
... kvoli tomu sa napr. na zac. telegramu posiela nejaka hlavicka, aby sa podla nej partnersky system synchronizoval so zaciatkom telegramu.
... niekedy sa stava opacna situacia: "vysielac" posle 3 telegramy po 100 bajtov, ale cez router a ine akt. cleny to "prijimac" prijme ako JEDEN 300 bajtovy tlg.

... aby si si to co najviac zjednodusil, tak odporucam posielat telegramy tak, ze budu stale rovnakej dlzky (ak je ina dlzka prijata, nez napr. 100 bajtov, tak taky tlg. zahodit;
... pri vysielani NEVYSIELAT telegramy hned za sebou (dat medzi ne povedzme 500ms, aspon pre skusku)
... ak pomozu tieto zmeny, tak az potom sa zaoberat rozdelovanim telegramov alebo synchronizaciou na zaciatku tlg.
... otazka este je, ci sa nahodou RPi po nejakom case neodpoji, a znovu rekonektuje;

... na toto by som v nejakom okne spustil PING z PC na RPi ... NESMIE mat vypadky

 
Nahoru Odpovědět
8.4.2016 13:01
Avatar
švrčajs
Člen
Avatar
švrčajs:13.4.2016 10:00

Ahoj,
nakonec jsem to vyřešil pomocí UDP, jednalo se mi u TCP o to, že šlo parádně využít k indikaci přerušení komunikace.. Takže jsem to celkově vyřešil takovou menší kličkou :D v klientovi ověřuji sílu signálu wifi, jakmile se dostane pod 20%, tak se model zastaví.. Sice to není dokonalé řešení, ale funguje.

Každopádně, díky za rady, budou se i tak hodit

 
Nahoru Odpovědět
13.4.2016 10:00
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 3 zpráv z 3.