Raspberry Pi ile Thread kullanarak TCP Server Uygulaması

Merhaba Arkadaşlar;

Uzun bir aradan sonra sizlere Raspberry pi ile C de Thread kullanarak TCP server yapımını anlatacağım. Öncelikle TCP, UDP ve soket ile ilgili konulara girmeyeceğim İnternet ortamında  yeterince bilgi mevcuttur. Biz işin kontrol kısmı yani nasıl veri transferi yada uzaktan kontrol yada sıcaklık okuma gibi kısımlarıyla ilgileneceğiz.

 

 

 

 

 

Öncelikle neden thread kullanılıyor ondan kısaca bahsedelim. Normal yöntem ile main içinde dönerek tcp isteği var mı diye bakarsak, diğer gelen verileri yada istekleri kaçırabiliriz. Bu gibi durumların olmaması için her gelen istek için bir thread açarsak gelen isteklerdeki dataları yorumlayıp hiç bir datayı kaçırmadan cevap vermiş oluruz. Kısaca TCP haberleşmesi için aşağıdaki data akışını inceleyebilirsiniz.

Raspberry pi yi TCP server için GSM modül kullanarak internet çıkışı sağladım. İlerleyen yazımda Quectel M66 modülü ile Raspberry Pi ye GPRS bağlantı nasıl sağlanır onu anlatacağım.

Ben yazılımda test için DS18B20 sensörünün sıcaklığını ve işlemci sıcaklığını gösteren komutlar belirledim. Bu komutlar geldiğinde Raspberry Pi ilgili cevabı istemci tarafa yani cilent tarafına gönderir.

  • <temp>         İşlemci ve DS18B20 sıcaklığını ister
  • <tempcpu>  Sadece işlemci sıcaklığını ister
  • <tempds>     Sadece DS18B20 deki sıcaklığı ister

siz bu aşamada istediğiniz şekilde data aktarabilirsiniz.

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/* 
 * File:   main.c
 * Author: UMUT
 *
 * Created on 21 Mart 2018 Çarşamba, 19:41
 */

#include <stdio.h>
#include <string.h>    //strlen
#include <stdlib.h>    //strlen
#include <sys/socket.h>
#include <arpa/inet.h> //inet_addr
#include <unistd.h>    //write
#include <pthread.h> //for threading , link with lpthread
#include <wiringPi.h>
#include <softPwm.h>
#include <stdint.h>
#include <unistd.h>

#define LED_puls    25
#define LED_com     24
#define ServerPort  8888

//the thread function
void *connection_handler(void *);
void GPIOinit(void);
uint16_t  GetCPUTemp();
uint16_t  GetDSTemp();
void LEDFlashThread(void);

char        TXbuffer[1024];
uint16_t    CPUTemp=0;
uint16_t    DSTemp=0;
char        *ptr1;  
uint16_t    GetCPUTemp();
uint16_t    GetDSTemp();

uint8_t     ResSts=0;

char CPUtempfile[] = {"/sys/class/thermal/thermal_zone0/temp"};
char DStempfile[] = {"/sys/devices/w1_bus_master1/28-0517c15e77ff/w1_slave"};


int main(int argc, char** argv) 
{
    int socket_desc , client_sock , c,t;
    struct sockaddr_in server , client;
    pthread_t thread_id,ledflth;
    
    
    wiringPiSetup();
    GPIOinit();
    
    pthread_create(&ledflth,NULL,LEDFlashThread,NULL);
    //pthread_join(ledflth,NULL);
  

    //Create socket
    socket_desc = socket(AF_INET , SOCK_STREAM , 0);
    if (socket_desc == -1)
    {
        printf("Could not create socket");
    }
    puts("Socket created");
     
    //Prepare the sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( ServerPort );
     
    //Bind
    if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
    {
        //print the error message
        perror("bind failed. Error");
        return 1;
    }
    puts("bind done");
     
    //Listen
    listen(socket_desc , 3);
     
    //Accept and incoming connection
    puts("Waiting for incoming connections...");
    c = sizeof(struct sockaddr_in);
     
    //Accept and incoming connection
    puts("Waiting for incoming connections...");
    c = sizeof(struct sockaddr_in);
    
    
    while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
    {
        puts("Connection accepted");
         
        if( pthread_create( &thread_id , NULL ,  connection_handler , (void*) &client_sock) < 0)
        {
            perror("could not create thread");
            return 1;
        }
         
        //Now join the thread , so that we dont terminate before the thread
        //pthread_join( thread_id , NULL);
        puts("Handler assigned");
    }
     
    if (client_sock < 0)
    {
        perror("accept failed");
        return 1;
    }

    return (EXIT_SUCCESS);
}



/*
 * This will handle connection for each client
 * */
void *connection_handler(void *socket_desc)
{
    //Get the socket descriptor
    int sock = *(int*)socket_desc;
    int read_size;
    char *message , client_message[2000];
     
    //Send some messages to the client
    //message = "RaspiZero Server Hosgeldiniz...\n";
    //write(sock , message , strlen(message));
     
     
    //Receive a message from client
    while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
    {
        ResSts=0;
        digitalWrite (LED_com, HIGH);
        
        //end of string marker
	client_message[read_size] = '\0';
		
	//gelen mesaj gonderilmek istenilirse aç
        //write(sock , client_message , strlen(client_message));
	
        
        //----
        if(strstr(client_message, "<temp>")!= NULL)
        {
            write(sock , "\r\nIslem yapiliyor...\r\n" , 22);
            CPUTemp = GetCPUTemp();
            DSTemp = GetDSTemp();
            sprintf(TXbuffer,"Islemci Sicaklik : %5.3f°C\nDS18B20 Sicaklik : %5.3f°C\r\n",(float) CPUTemp / 1000,(float) DSTemp / 1000);
            write(sock , TXbuffer , strlen(TXbuffer));
            ResSts=1;
        }
        
        if(strstr(client_message, "<tempcpu>")!= NULL)
        {
            CPUTemp = GetCPUTemp();
            sprintf(TXbuffer,"%5.3f°C\n",(float) CPUTemp / 1000);
            write(sock , TXbuffer , strlen(TXbuffer));
            ResSts=1;
        }
        
        if(strstr(client_message, "<tempds>")!= NULL)
        {
            DSTemp = GetDSTemp();
            sprintf(TXbuffer,"%5.3f°C\n",(float) DSTemp / 1000);
            write(sock , TXbuffer , strlen(TXbuffer));
            ResSts=1;   
        }
        //---     
    
        if(ResSts==0)
            write(sock , "Hata\r\n" , 6);	
 
        
	//clear the message buffer
	memset(client_message, 0, 2000);
        
        digitalWrite (LED_com, LOW);
    }
     
    if(read_size == 0)
    {
        puts("Client disconnected");
        fflush(stdout);
    }
    else if(read_size == -1)
    {
        perror("recv failed");
    }
         
    return 0;
} 


void GPIOinit(void)
{
    pinMode (LED_puls, OUTPUT);
    pinMode (LED_com, OUTPUT);
    pinMode (23, OUTPUT);//led karti icin
    pinMode (22, OUTPUT);//led karti icin
    pinMode (21, OUTPUT);//led karti icin
    digitalWrite (LED_puls, LOW); 
    digitalWrite (LED_com, LOW);
}


uint16_t  GetCPUTemp()
{
    FILE *fp;
    char filebuffer[100];
	
    if((fp=fopen(CPUtempfile,"r")) == NULL)
    {
	printf("Dosya açma hatası!\n(%s) Bulunamadı ...\n",CPUtempfile);
	exit(EXIT_FAILURE);
    }	
    fread(filebuffer, sizeof(filebuffer), 1, fp);
    fclose(fp);
    return atoi(filebuffer);
}

uint16_t  GetDSTemp()
{
    FILE *fp;
    char filebuffer[100];

    if((fp=fopen(DStempfile,"r")) == NULL)
    {
        printf("Dosya açma hatası!\n(%s) Bulunamadı ...\n",DStempfile);
	exit(EXIT_FAILURE);
    }
    fread(filebuffer, sizeof(filebuffer), 1, fp);
    fclose(fp);
    ptr1 = strstr(filebuffer, "t=");
    ptr1 = ptr1 + 2;
    return atoi(ptr1);	
}

void LEDFlashThread(void)
{
    while(1)
    {
        digitalWrite (LED_puls, HIGH);
        delay(100);
        digitalWrite (LED_puls, LOW);
        delay(900);
    }
}

Program hakkında detaylar;

  • DS18B20 sensörü kullanacaksanız daha önceki yazılarımdan nasıl ve hangi pine bağlandığına bakabilirsiniz. Okumak için sensörün rom koduna ihtiyaç vardır ve bu kodu aşağıdaki gibi satırda değiştireceksiniz. 28-0517c15e77ff
    char DStempfile[] = {"/sys/devices/w1_bus_master1/28-0517c15e77ff/w1_slave"};
  • Led pinlerini ve dinleyeceği port u değiştirebilirsiniz.
    #define LED_puls    25
    #define LED_com     24
    #define ServerPort  8888
  • Client tarafında bağlantı gerçekleştiğinde mesaj göndermek için bu kısmı açabilirsiniz.
    Send some messages to the client
    message = "RaspiZero Server Hosgeldiniz...\n";
    write(sock , message , strlen(message));
  • Gelen mesajı tekrar ettirmek istiyorsanız bu kısmı açabilirsiniz.
    //gelen mesaj gonderilmek istenilirse aç
    write(sock , client_message , strlen(client_message));

 

Bir başka yazımda görüşmek üzere, kolay gelsin…

(Her türlü öneri ve görüşleriniz için iletişim sayfamı kullanabilirsiniz.)

“Raspberry Pi ile Thread kullanarak TCP Server Uygulaması” için 1 yorum

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.