LINUX.ORG.RU

Сообщения stD

 

Ищу работу - Линукс, программирование

Форум — Job

Что могу:

Линукс - пользую лет 10-15, в виндовсе не разбираюсь (пользователь на уровне Call of Duty).

Немного разбираюсь в серверах (софт), отчасти понимаю что такое OSI, и даже могу написать простой сервер на СИ, то бишь немного умею программить на СИ. (это пожалуй самое интересное для меня)

Могу мышкой напрограммировать кнопок на форме в каком-нибудь DelphiБилдере и связать это с каким-нибудь дивайсом, висящим на ком-порту.

Так же знаком с PHP, JS и т.д.

Держу свой сайт. (делал всё сам, начиная с сервера и заканчивая статьями на нём).

Неплохо разбираюсь в OpenWrt.

Люблю строить свой «умный дом». (вполне успешно)

Немного разбираюсь в программировании МК и много в Ардуине (понимаю почему Ардуино - это зло, и за что её ругают джедаи «Atmel Studio»). (есть желание осваивать 32-ух битные МК)

Есть желание работать и учиться (или наоборот).

...

Мои пожелания:

Удалённая работа.

...

Если есть на свете работодатель, которого заинтересует набор таких компетенций, то прошу писать на почту pccar@mail.ru. Место проживания - СПб. м.Большевиков.

И таки да, мне 40 лет и я бородат. (это правда)

Да, чуть не забыл, приложения для Андройда ещё могу.

 

stD
()

Про Makefile Openwrt

Форум — General

Здравствуйте.

Про кросскомпиляцию отдельных пакетов для Openwrt.

Прошу помощи.

Для Openwrt, для отдельного пакета (например homestd.c) собираю вот с таким мейкфалом:

include $(TOPDIR)/rules.mk

PKG_NAME:=homestd
PKG_VERSION:=1
PKG_RELEASE:=1

PKG_BUILD_DIR:= $(BUILD_DIR)/$(PKG_NAME)

include $(INCLUDE_DIR)/package.mk


define Package/homestd
	SECTION:=utils
	CATEGORY:=Utilities
	TITLE:=homestd - Homestd utility
	DEPENDS:=+libpthread
endef

define Package/homestd/description
    homestd - Homestd utility
endef

define Build/Prepare
	mkdir -p $(PKG_BUILD_DIR)
	$(CP) ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Compile
	$(TARGET_CC)  $(TARGET_CFLAGS) -c  -o $(PKG_BUILD_DIR)/homestd.o $(PKG_BUILD_DIR)/homestd.c 
	$(TARGET_CC) $(TARGET_LDFLAGS) -o  $(PKG_BUILD_DIR)/homestd $(PKG_BUILD_DIR)/homestd.o -lpthread
endef

define Package/homestd/install
	$(INSTALL_DIR) $(1)/
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/homestd $(1)/
endef

$(eval $(call BuildPackage,homestd))

Сейчас хочу скомпилить некую программу для Openwrt. Программа (для некой девайсины от Мастеркита) поставляется с файлами hidapi.h, hid-libusb.c, mp751.c.

И с файлом install.sh

#!/bin/bash
cd
sudo apt-get install g++ libusb-1.0-0-dev
cd /home/pi/mp751
sudo make clean
sudo make
sudo rm mp751.o hid-libusb.o
И в придачу даётся Makefile для ubuntu/debian вот с таким содержанием:

all: mp751

mp751: mp751.o hid-libusb.o
	gcc mp751.o hid-libusb.o -o mp751 -lusb-1.0 -lrt -lpthread

mp751.o: mp751.c
	gcc -c mp751.c
	
hid-libusb.o: hid-libusb.c 
	gcc -I/usr/include/libusb-1.0 -I. -c hid-libusb.c

clean:
	rm -f hid-libusb.o mp751.o mp751

.PHONY: clean

Объясните пожалуйста или покажите пример, как совместить эти два мейкфайла? Или точнее превратить этот мейкфайл в мейкфайл для OpenWrt?

Спасибо.

 

stD
()

Про web-socket

Форум — General

Здравствуйте.

Допустим я установил связь меду клиентом и сервером с помощью web-socket, всё хорошо, время от времени я обмениваюсь с сервером какими-то сообщениями. И вот в какой-то момент сервер послал мне сообщение и оно потерялось на каком-то промежуточном хопе.

Вопрос: что будет, я так и не узаю про это сообщение?

 

stD
()

Функция popen() - язык СИ

Форум — Development

Здравствуйте.

Есть некая программа, неважно что она делает (в крестики-нолики сама с собой играет). В ней есть отдельный поток, задача которого, запускать скрипт «pinre.sh» и считывать результат работы этого скрипта:

#!/bin/sh

BCM0=`cat /home/dima/test.txt`
BCM1=`cat /home/dima/test2.txt`
BCM2=`cat /home/dima/test3.txt`

S2="$BCM0 $BCM1 $BCM2"
echo "$S2"

exit 0

Скрипт опрашивает три файла (test*.txt), собирает результат в строку и делает echo «$S2», тоесть выплёвывает строку «bla1 bla2 bla3».

Вот поток, который запускает скрипт и ловит ответ:

...
void * thr_fnc() 
 { 
   for(;;) 
    { 
      sleep(1);

      FILE * read_pins;
      char in_data[16];

      read_pins = popen("pinre.sh", "r");

      int lastchar = fread(in_data, 1, 15, read_pins);
      in_data[lastchar] = '\0';
      printf("Data:%s", in_data);
      pclose(read_pins);
    } 

   return 0;

 } 
...

Вопрос заключается вот в чём: что из себя в данном случае представляет FILE * read_pins;, это какой-то файл, который создаётся на диске или область в памяти выделяется? Или это ещё что-то?

Перемещено leave из general

 

stD
()

«Нотариально заверенный» комментарий

Форум — Talks

Не знает ли кто-нибудь, есть ли такой онлайн-сервис, чтоб можно было написать там что либо и это бы считалось непоколебимым пруфом. То есть что-то типа нотариальной конторы только без женщин с «халами» на головах и прочей бюрократической ереси.

Например, человек обещает мне что-то, я ему говорю - «напиши своё обещание на таком-то ресурсе», он пишет, и в случае отказа я могу предъявить ему эту запись.

Перемещено beastie из science

 

stD
()

Сделайте кнопки для вставки тегов!

Форум — Linux-org-ru

Это же какой-то каменный век, сделайте пожалуйста кнопки для тегов, выделил фразу и нажал кнопку «жирный текст» или «подчёркнутый текст» и т.д.

 ,

stD
()

Сколько стоит написать прошивка для роутера

Форум — Development

Человек предложил написать прошивку для китайского роутера, я так понимаю можно за основу взять Openwrt, но вот вопрос - сколько это может стоить? Хотя бы ориентировочно.

 

stD
()

comparison is always true due to limited range of data type

Форум — General

Здравствуйте.

Компиляция программы на СИ.

Поясните пожалуйста такую вещь, вот часть кода...

Читаю из файла:

 
   char ch;
   while(ch!=EOF) 
    {
      ...
    }

Если компилировать на большом компе (х86), то ошибки отсутствуют.

Версия компилятора:

 
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3)

А если делаю то же самое на RaspberryPi2 (ARM), то говорит, что «сравнение всегда верно из-за ограниченного диапазона типа данных» (comparison is always true due to limited range of data type [-Werror=type-limits]).

Что ему не нравится?

Версия компилятора RPi:

 
gcc version 4.9.2 (Raspbian 4.9.2-10)

 

stD
()

Как сервер отдаёт картинки?

Форум — General

Здравствуйте.

Я пишу маленький серверок на СИ, работа которого заключается в отдаче html-странички и css-файла. С текстовыми файлами вроде просто, открыл файл ⇨ прочитал ⇨ отдал клиенту.

Скажите, а как отдавать картинки? Если можно пример. Спасибо.

 

stD
()

Обновление Debian

Форум — General

Здравствуйте.

Полагаю, что мой вопрос покажется странным, а может и глупым, но тем не менее спрошу...

Недавно перевел свой сервер с ubuntu на debian и возник вопрос, а надо ли обновлять debian?

Почему спрашиваю: я всегда представлял себе убунту как некую девочку, которой нужно то да сё, а Debian это такой мужик в нестираных трусах, который ни в чём не нуждается и только работает, работает и работает...

uname -a

Linux debian 3.16.0-4-686-pae #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) i686 GNU/Linux

 

stD
()

Изоляция пользователей на сайте

Форум — General

Здравствуйте.

Делаю у себя на сайте некий конструктор интерфейса, работающего на пхп-скриптах, суть которого заключается в том, что человек выбирая некие параметры и нажимая кнопку «далее», в итоге получает набор готовых файлов (index.html и т.д.).

Вопрос заключается в том, как сделать чтоб в случае работы двух или более пользователей, их действия не пересеклись? То есть, чтоб они не насоздавали файлов с непонятным содержимым.

В голову приходит создавать для каждого пользователя файлы с разными названиями, то есть типа «index.html.000001. Но это не совсем удобно, да и вынуждает человека регаться.

Подскажите какие ещё есть возможности изолировать работу клиентов на сайте? Как вобще в таких случаях поступают?

 

stD
()

Переходы на свой сайт

Форум — Web-development

Здравствуйте.

Не знаю может сказанное окажется глупостью, однако всё равно спрошу.

Что если оставлять какие-либо ссылки на каких-либо форумах (да хотя бы здесь) таким образом, чтоб человек нажимая на неё переходил сначала на мой сайт, а оттуда редиректился уже на искомый ресурс. Будет ли это полезно, в контексте SEO, для моего сайта ?

Перемещено leave из general

 

stD
()

Создать профсоюз работников IT

Форум — Talks

Давайте создадим профсоюз.

Почитал тут как это делается:

Найти единомышленников - с этим нет проблем.

Определитесь, в какой отраслевой профсоюз вы войдёте - определено.

Проведите агитационно-пропагандистскую работу - для начала можно создать отдельный раздел на форуме, а ещё лучше выделить отдельный ресурс.

Расскажите своим коллегам, для чего нужен профсоюз и чем он занимается. Познакомьте их с понятиями «отраслевое соглашение» и «коллективный договор», расскажите, как с их помощью можно регулировать заработную плату, добиваться улучшения условий труда, получать социальные гарантии и тому подобным.

Проведите учредительное профсоюзное собрание - да сколько угодно и в любой момент.

...

Начну с поиска единомышленников...

Перемещено beastie из job

 

stD
()

Функция read() (СИ) в openwrt

Форум — General

Здравствуйте.

Может кто сталкивался с таким явлением, а может я что-то не так делаю...

Есть программа на СИ, которая работает на роутере и читает даные от ардуиы (/dev/ttyUSB), делается так:

...
int open_port()  
 {  
   int fd;  
   fd = open(device, O_RDWR | O_NOCTTY); 
...

   options.c_cflag |= (CLOCAL | CREAD); 
   options.c_cflag &= ~PARENB;  
   options.c_cflag &= ~CSTOPB;  
   options.c_cflag &= ~CSIZE;  
   options.c_cflag |= CS8;  
   options.c_cc[VMIN] = 1;  
   options.c_cc[VTIME] = 1;  
   options.c_lflag = ICANON;  
   options.c_oflag = 0;  
   options.c_oflag &= ~OPOST; 
   tcflush(fd, TCIFLUSH);
   tcsetattr(fd, TCSANOW, &options);
... 

...
while(!VINTR) 
    {  
      int bytes = 0;
      memset(bRead, 0, sizeof(bRead));

      if((bytes = read(fd, bRead, BUFSIZE))==-1) // read()
        {
          printf("Error_Read_from_Arduino\n");
        }

      printf("Rec: %s", bRead);
...

Из ардуины строка отправляется вот так:

   Serial.print(1); 
   Serial.print(" "); 
   Serial.print(2); 
   Serial.print(" "); 
   Serial.print(3); 
   Serial.println(); 

То есть на конце - \r\n.

Если запускать прогу на большом компе, то строка принимается полностью, то есть «1 2 3\r\n», bytes говорит что прочитано 7 символов.

Если запускать прогу на роутере, то принимается строка - «1 2 3\r» (6 символов), а потом отдельно принимется символ «\n».

То есть получается, что как будто функция read работает по другому.

Скажите, почему так? Или я где-то ошибаюсь?

Или надо где-то указывать компилятору, что считать концом строки?

Для компа компилятор gcc 4.8, для роутера gcc 4.6.

 

stD
()

Непонятности в чтении /dev/ttyUSB

Форум — General

Здраствуйте.

Есть программа работающая на роутере (asus wl-500), которая читает данные от ардуины и пресылает их куда надо.

Вот так открываю порт:

int open_port()  
 {  
   int fd;  
   fd = open(device, O_RDWR | O_NOCTTY); //|O_NONBLOCK); 
 
   if(fd == -1) 
     {  
       strncpy(er_log_str, "Error - NOT open port.", 31);
       error_log();
     }

   else  
     {  
       struct termios options;  
       tcgetattr(fd, &options);  
       cfsetispeed(&options, B57600);  
       cfsetospeed(&options, B57600);  
       options.c_cflag |= (CLOCAL | CREAD); 
       options.c_cflag &= ~PARENB;  
       options.c_cflag &= ~CSTOPB;  
       options.c_cflag &= ~CSIZE;  
       options.c_cflag |= CS8;  
       options.c_cc[VMIN] = 1;  
       options.c_cc[VTIME] = 1;  
       options.c_lflag = ICANON;  
       options.c_oflag = 0;  
       options.c_oflag &= ~OPOST; 
       tcflush(fd, TCIFLUSH);
       tcsetattr(fd, TCSANOW, &options);  
     }  

   return fd;  
 }

...

В цикле ожидаю данных (ардуина посылает их ~два раза в сек.). Чтение блокируется пока нет данных.

...
  char bRead[BUFSIZE] = {0,}; 
  int err_count1 = 0; 
  unsigned int i = 0;


  while(!VINTR) 
   {     
      int bytes = 0;
      memset(bRead, 0, sizeof(bRead));

      if((bytes = read(fd, bRead, BUFSIZE))==-1)
        {
          printf("Error read.\n");
        }

      printf("bytes: %d\n\n", bytes); 

      for(i = 0; i<=strlen(bRead); i++)
       {
         if(bRead[i] == '\r' || bRead[i] == '\n')
          {
            bRead[i] = 0;
            tcflush(fd, TCIFLUSH); 
            break;
          }
       } 

     //////////////////////// Проверка A-Z /////////////////////////////////////
     if(bRead[0] == 'A' && bRead[strlen(bRead)-1] == 'Z')     
      {
        err_count1 = 0;
        printf("OK A-Z\n"); 
      }

     else
      {
        tcflush(fd, TCIFLUSH);  
        err_count1++;
      
        if(err_count1 > 10) 
          {
            strncpy(er_log_str, "Not A-Z.", 31);
            error_log();
          }

        printf("Not_A-Z_bRead: %s\n\n", bRead); 
        continue;
      } 

     host = gethostbyname("192.168.1.1"); // 192.168.1.1
     memset((char *) &server, 0, sizeof(struct sockaddr_in));
     server.sin_family = AF_INET;
     server.sin_port = htons(3495);
     server.sin_addr = *((struct in_addr*) host->h_addr);

     if(sendto(sockfd, bRead, strlen(bRead), 0, (struct sockaddr *) &server, sizeof(server)) < 0)
        {
           strncpy(er_log_str, "ERROR sendto.", 31);
           error_log();
        }

     printf("bRead: %s\n\n", bRead);
    

   } // Конец основного цикла (while) 
...

Суть работы такова:

Ардуина посылает строку - «A 1 1 1 1 1 1 1 1 1 1 1 0 0 Z».

read() - её ловит.

for(i = 0; i<=strlen(bRead); i++) - отыскивает конец строки.

if(bRead[0] == 'A' && bRead[strlen(bRead)-1] == 'Z') - проверяет первый и последний символ, и если всё хорошо, тогда эти данные отправляются по UDP.

Если проверка «A...Z» неудачная, то возврат к началу цикла (while(!VINTR)).

Вопрос заключается в следующем:

В представленном выше виде, всё работает хорошо, ошибок «A...Z» нет. Однако если убрать строчку «printf(„bytes: %d\n\n“, bytes);», которая идёт после read():

...
  while(!VINTR) 
   {     
      int bytes = 0;
      memset(bRead, 0, sizeof(bRead));

      if((bytes = read(fd, bRead, BUFSIZE))==-1)
        {
          printf("Error read.\n");
        }

      printf("bytes: %d\n\n", bytes); // эта строчка
...
Тогда время от времени начинает появляться ошибка «Not_A-Z_bRead:», причём массив «bRead» пустой, то есть как будто ничего не получено.
...
  if(err_count1 > 10) 
   {
     strncpy(er_log_str, "Not A-Z.", 31);
     error_log();
   }

  printf("Not_A-Z_bRead: %s\n\n", bRead); 
  continue;
...

Если вместо злосчастной строки «printf(„bytes: %d\n\n“, bytes);» вставить паузу, хотя бы на одну микросекунду (usleep(1);), то ошибка исчезает. Иными словами, получается что после read() зачем-то нужна крохотная задержка.

Как объяснить такое поведение? Причём это проявляется только на роутере, если запускать прогу на «большом компе», то ошибок нет.

 

stD
()

Сайт на английском

Форум — Web-development

Здравствуйте.

Есть сайт про всякое «компьютерное» на русском языке, хочется перевести его на английский и «выйти на международное пространство»). Как лучше/правильней сделать, совместить две версии (английскую и русскую) на одном домене (.ru) или сделать английскую копию на например .сом?

Как вообще в таких случаях поступают?

 

stD
()

Заменить пхпшный файл регистрации на СИшный

Форум — General

Здравствуйте.

Появилась задача сделать регистрацию на сайте, почитал ряд на тем по этому вопросу и понял что в основном всё сводится к связке PHP + MySOL. То есть пхпешный файл ловит данные введённые пользователем и заносит их в базу, предварительно обрабатывая (удаление лишних символов, хеширование, ограничение кол-ва неверных вводов).

Подумалось вот что, ведь если «хулиган» каким-то образом заполучит этот самый пхп-файл (в котором происходит обработка), то он узнает все применённые хитрости.

Отсюда вопрос, что если вместо пхп написать всё то же самое на СИ?

Разумеется это не будет панацеей, но однако же возможно снизит риск.

Прошу сообщество отнестись к данной теме непредвзято и в случае моей неправоты дать объяснение.

 

stD
()

UDP-клиент OpenVpn

Форум — General

Здравствуйте.

Вопрос является продолжением написанного здесь.

Как отправить широковещательный пакет в vpn-туннель.

Есть роутер (стоящий дома) с адресом 192.168.1.1. На нём поднят vpn-сервер, адрес 10.25.0.0, маска 255.255.255.0. На нём же крутится udp-клиент («трансивер»), который отправляет пакеты в туннель.

Так вот, если отправлять пакет например на адрес 10.25.0.6 (это подключённый смартфон), то пакет долетает, всё гуд.

А как сделать, чтоб отправлять широковещательный пакет нескольким смартфонам подключённым к vpn-серверу?

Вот код:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int nwe=1;
    int sockfd; 
    int n; 
    
    struct sockaddr_in servaddr, cliaddr; 
    

    
    if(argc != 3){
        printf("IP address rout, IP address tel\n");
    }
  
    if((sockfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
      {
        perror(NULL); 
      }


    setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&nwe,sizeof(nwe));

    
    memset(&cliaddr, 0, sizeof(cliaddr));
    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(3495);
    //cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);

    if(inet_aton(argv[1], &cliaddr.sin_addr) == 0)
      {
        printf("Invalid IP address\n");
        close(sockfd); 
      }    
    
    

    if(bind(sockfd, (struct sockaddr *) &cliaddr,  sizeof(cliaddr)) < 0)
      {
        perror(NULL);
        printf("Invalid bind\n");
        close(sockfd); 
      }
    

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(3492);
    
    if(inet_aton(argv[2], &servaddr.sin_addr) == 0)
      {
        printf("Invalid IP address2\n");
        close(sockfd); 
      }
    
    
    while (1) 
     {
        usleep(910000);
        char sendline[] = "paket leti)))";
      
        if(sendto(sockfd, sendline, strlen(sendline)+1,  0, (struct sockaddr *) &servaddr,  sizeof(servaddr)) < 0)
          {
            perror(NULL);
            printf("Invalid IP sendto\n");
            close(sockfd);
          }

        printf("bla-bla: %s\n", sendline);

      }

    close(sockfd);
    return 0;
}

Заранее благодарю за наставления на путь истинный.

 

stD
()

UDP-клиент

Форум — General

Здравствуйте.

Возник вопрос следующего характера. Есть домашняя сеть состоящая из роутера (wl500, прошивка tomato) и трёх подключённых к нему компьютеров (линукс).

Адрес роутера 192.168.5.99, компьютеры получают адреса по dhcp (192.168.5.197, 192.168.5.224, 192.168.5.234).

На компах крутятся udp-сервера.

Что хочу

Хочу чтоб на роутере работал udp-клиент и отправлял ВСЕМ компам некий пакет (просто строка символов).

Вот сам udp-клиент:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define SERVERPORT "3492"    

int main(int argc, char *argv[])
{
    int sockfd;
    struct addrinfo hints, *servinfo, *p;
    int rv;
    int numbytes;
    int n=1;

    if (argc != 2) {
        exit(1);
    }

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_DGRAM;
    

    if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

   
    for(p = servinfo; p != NULL; p = p->ai_next) 
     {
        if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) 
          {
            continue;
          }

        break;
     }

    setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&n,sizeof(n)); 

    if (p == NULL) {
        return 2;
    }


    char str_iz_file[128] = {0,};

    while (1) 
      {
          usleep(910000);  

          FILE *f; 
          f = fopen("/tmp/file.db", "r"); // tmp
          if(f == NULL) 
            {
              continue;
            } 

           fgets(str_iz_file, 127, f);
           fclose(f); 


           if ((numbytes = sendto(sockfd, str_iz_file, strlen(str_iz_file), 0, p->ai_addr, p->ai_addrlen)) == -1) {
           
           exit(1);
           }

           printf("bla-bla: %s\n", str_iz_file);

           memset(str_iz_file, 0, sizeof(str_iz_file));

      }

    freeaddrinfo(servinfo);
  
    close(sockfd);

    return 0;
}

//gcc -W -Wall udpclient.c -o udpclient
//  make package/udpclient/compile V=s
// ./udpclient 255.255.255.255

Запускаю вот так: ./udpclient 255.255.255.255

Вопрос заключается в том, что если запускать udpclient на одном из компов, то всё отлично, другие компы получают пакет, а вот если запустить его на роутере, то никто ничего не получает.

Объясните пожалуйста, что я делаю не так?

 

stD
()

Сервер на СИ

Форум — Development

Здравствуйте.

В данное время я медленно, но с удовольствием постигаю прекрасный язык СИ (до этого было делфи, пхп, js и ещё что-то).

ПРОЛОГ

Мне понадобился маленький тср-серверок, который бы слушал порт, принимал от клиента некий символ (например букву А) и далее отправлял этот символ в микроконтроллер подключённый к серверу по USB. (Всё это связано с пресловутым «умным домом»)

СУТЬ

На просторах интернета я нашёл не малое количество примеров и остановился вот на этом - http://masandilov.ru/network/guide_to_network_programming6#6.1

После некоторых изменений, код приобрёл нижеследующий облик:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>

#define BACKLOG 10     // как много может быть ожидающих соединений

#define MAXBUFLEN 100

char PORT[5]={0,};
char device[14]={0,};
char er_log_str[50]={0,};

void sigchld_handler()
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
}

void *get_in_addr(struct sockaddr *sa) // получаем адрес сокета, ipv4 или ipv6:
{
    if(sa->sa_family == AF_INET) 
     {
       return &(((struct sockaddr_in*)sa)->sin_addr);
     }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

void error_log() // запись ошибки в файл ErrorSer.log
{  
    time_t t;
    time(&t);
    FILE *f;
    f = fopen("ErrorSer.log", "a"); 
    fprintf(f , "%s. ", er_log_str);
    fprintf(f , "%s", ctime( &t));  
    printf("Write to ErrorSer.log\n");
    fclose(f);
    exit(0);
}

int main(int argc, char *argv[])
{
   if(argc!=3) 
    {
      printf("Primer zapyska - ./arduserver 3490 /dev/ttyACM1\n");
      sprintf(er_log_str,"%s","Not use PORT");
      error_log();
    }
  
   sprintf(PORT,"%s", argv[1]);
   sprintf(device,"%s", argv[2]);

    int sockfd, new_fd;  // слушаем на sock_fd, новые соединения - на new_fd
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_storage their_addr; // информация об адресе клиента
    socklen_t sin_size;
    struct sigaction sa;
    int yes=1;
    // char s[INET6_ADDRSTRLEN];
    int rv;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // use my IP

    if((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) 
      {
        sprintf(er_log_str,"%s","Error - getaddrinfo");
        error_log();
      }

    for(p = servinfo; p != NULL; p = p->ai_next) // цикл через все результаты, чтобы забиндиться на первом возможном
      {
        if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) 
          {
            perror("server: socket");
            continue;
          }

        if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) 
          {
            perror("setsockopt");
            exit(1);
          }

        if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) 
          {
            close(sockfd);
            perror("server: bind");
            continue;
          }

        break;
      }

    if(p == NULL)  
     {
        sprintf(er_log_str,"%s","Error - failed to bindn");
        error_log();
     }
   
    freeaddrinfo(servinfo); // всё, что можно, с этой структурой мы сделали

    if(listen(sockfd, BACKLOG) == -1) 
     {
        sprintf(er_log_str,"%s","Error - listen");
        error_log();
     }

    sa.sa_handler = sigchld_handler; // обрабатываем мёртвые процессы
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;

    if(sigaction(SIGCHLD, &sa, NULL) == -1) 
     {
        sprintf(er_log_str,"%s","Error - sigaction");
        error_log();
     }

    printf("server: waiting for connections...\n");

    while(1) // главный цикл accept()
     {  
        sin_size = sizeof their_addr;
        new_fd = accept(sockfd, NULL,  &sin_size);

        if(new_fd == -1) 
         {
            perror("accept");
            continue;
         }

        printf("server: OK connection\n");

///////////////////////////////////////////////////////////////////////////////////////////

        if(!fork()) // тут начинается дочерний процесс
           { 
            close(sockfd); // дочернему процессу не нужен слушающий сокет
          
            char buffer[7] = {0,};

            int n = read(new_fd, buffer, 6);

            if(n < 0)
              {
                sprintf(er_log_str,"%s","Error - reading from socket");
                error_log();
              }

            printf("\n"); 
            printf("Ot klienta polycheno: %c\n\n", buffer[5]); 

            char to_Ardu[14] = {0,}; 
            sprintf(to_Ardu,"echo 'Y+=Z%c' > %s", buffer[5], device);
            system(to_Ardu); // отправляем ардуине пакетик

            close(new_fd);

            exit(0);
        }

        close(new_fd);  // а этот сокет больше не нужен родителю

    } // конец while

    return 0;
}

/// ./arduserver 3490 /dev/ttyACM1

ВОПРОС

Очень хочется, чтоб уважаемое сообщество указало на ошибки в коде и объяснило некоторые моменты.

В частности:

1. Корректно ли я инициализирую массивы.

char PORT[5]={0,};

2. Нужен ли в данном примере дочерний процесс

if(!fork())
...
Это пока для меня тёмный лес, поэтому я был бы премного благодарен, если кто-то растолкует популярным языком, в каких случая надо запускать дочерние процессы.

Зараннее спасибо.

 ,

stD
()

RSS подписка на новые темы