Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
0 / 0 / 0
Регистрация: 26.11.2017
Сообщений: 289
1

Организация двусторонней связи

07.06.2019, 10:27. Показов 1157. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Помогите организовать двустороннюю связь
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include<stdlib.h>
int main(){
    int fd[2], result;
    size_t size;
    char resstring[14]; 
    /* Попытаемся создать pipe */
    if(pipe(fd) < 0){
        /* Если создать pipe не удалось, печатаем об этом сообщение
        и прекращаем работу */
        printf("Can\'t create pipe\n");
        exit(-1); 
    } 
    /* Порождаем новый процесс */ 
    result = fork(); 
    if(result < 0){ 
        /* Если создать процесс не удалось, сообщаем об этом и 
        завершаем работу */
        printf("Can\'t fork child\n");
        exit(-1);
    } else if (result > 0) {
        /* Мы находимся в родительском процессе, который будет 
        передавать информацию процессу-ребенку. В этом процессе
        выходной поток данных нам не понадобится, поэтому 
        закрываем его.*/
        close(fd[0]);
        /* Пробуем записать в pipe 14 байт, т.е. всю строку 
        "Hello, world!" вместе с признаком конца строки */
        size = write(fd[1], "Hello, world!", 14);
        if(size != 14){
            /* Если записалось меньшее количество байт, сообщаем
            об ошибке и завершаем работу */
            printf("Can\'t write all string\n"); 
            exit(-1); 
        } 
        /* Закрываем входной поток данных, на этом 
        родитель прекращает работу */
        close(fd[1]);
        printf("Parent exit\n");
    } else {
        /* Мы находимся в порожденном процессе, который будет 
        получать информацию от процесса-родителя. Он унаследовал
        от родителя таблицу открытых файлов и, зная файловые 
        дескрипторы, соответствующие pipe, может их использовать.
        В этом процессе входной поток данных нам не 
        понадобится, поэтому закрываем его.*/
        close(fd[1]);
        /* Пробуем прочитать из канала 14 байт в массив, т.е. всю
        записанную строку */
        size = read(fd[0], resstring, 14);
        if(size < 0){
            /* Если прочитать не смогли, сообщаем об ошибке и
            завершаем работу */
            printf("Can\'t read string\n"); 
            exit(-1); 
        } 
        /* Печатаем прочитанную строку */
        printf("%s\n",resstring);
        /* Закрываем входной поток и завершаем работу */
        close(fd[0]);
    }    
    return 0; 
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.06.2019, 10:27
Ответы с готовыми решениями:

Организация связи в БД
Суть в том что есть таблица &quot;заказы&quot;, которая содержит информацию о заказах; есть таблица...

Организация связи
eсть 6 двухпроводных линии (телефоный кабель) связи метров по 500-800. Есть 1 мастер, который будет...

Организация почтовой связи
Допустим я хочу из электронного ящика scott@tut.by послать письмо на ящик cartman@yandex.ru. Я...

Организация связи двух субформ
Здравствуйте! Пытаюсь для источника основного поля субформы сделать поле другой субформы. Всё...

4
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,888
07.06.2019, 11:01 2
Открыть два канала. Один от родителя к потомку, второй наоборот

Добавлено через 8 минут
Еще хочется сказать что код у вас оформлен на удивление хорошо (не принимайте близко к сердцу, тут на форуме это редкость). Правда, лично на мой взгляд, комментариев многовато, но, что радует, они по осмысленные и по делу.
Но есть и пара недочетов:
1. read и write возвращают не size_t, а ssize_t, знаковый.
2. Родительский процесс должен дождаться завершения всех дочерних. Не то чтобы это было так уж обязательно, но лучше так, чем оставлять детей сиротами.
3. Никто не гарантирует очередность запуска родительского и дочерних процессов. То есть не исключена ситуация, что сначала запустится ребенок, который попытается прочитать из файла и не преуспеет. Впрочем, у вас используется блокирующая работа с каналами, так что свои 14 байт он получит в любом случае. Но тем не менее, учесть это стоит.

Добавлено через 15 минут
В целом, я бы модифицировал вашу программу так:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
 
int main(){
  int ptc[2]; //parent to child [0]-передача, [1]-прием
  int ctp[2]; //child to parent
  pid_t pid;
  ssize_t size;
  char buf[100]; //у нас 8 МБ на стеке на халяву, для буфера можно выделить с запасом 
  
  if(pipe(ptc) < 0){ //открываем канал от родителя к ребенку
    printf("Can\'t create pipe\n");
    return -1;
  }
  if(pipe(ctp) < 0){ //открываем обратный канал
    printf("Can\'t create pipe\n");
    close(ptc[0]); close(ptc[1]);
    return -1;
  }
  
  pid = fork(); 
  if(pid < 0){ //не удалось клонироваться
    printf("Can\'t fork child\n");
    return -2;
  }else if (pid > 0){ //родительский процесс
    close(ptc[0]);
    close(ctp[1]);
    size = write(ptc[1], "Hello, child!", 14);
    if(size != 14){printf("P: Can\'t write all string\n"); return -3;}
    
    size = read(ctp[0], buf, 15);
    if(size < 0){printf("P: Can\'t read string\n"); return -4;} 
    printf("P: [%s]\n", buf);
    
    close(ptc[1]);
    close(ctp[0]);
    printf("Wait for child %i\n", pid);
    waitpid(pid, NULL, 0);
    printf("Parent exit\n");
  }else{ //дочерний процесс
    close(ptc[1]);
    close(ctp[0]);
    
    size = read(ptc[0], buf, 14);
    if(size < 0){printf("C: Can\'t read string\n"); return -5;} 
    printf("C: [%s]\n", buf);
    
    size = write(ctp[1], "Hello, parent!", 15);
    if(size != 15){printf("C: Can\'t write all string\n"); return -6;}
    
    close(ptc[0]);
    close(ctp[1]);
    
    usleep(1000); //немножко подождем чтобы родитель успел осознать что дочерний процесс завершился
    printf("Child exit\n");
  }
  return 0; 
}
Код
$ gcc main.c -Wall -Wextra
$ ./a.out 
C: [Hello, child!]
P: [Hello, parent!]
Wait for child 2441
Child exit
Parent exit
Обратите внимание на типы pid_t, ssize_t и упомянутые ранее замечания.
0
0 / 0 / 0
Регистрация: 26.11.2017
Сообщений: 289
22.06.2019, 13:19  [ТС] 3
Делаю во FreeBSD комплируется без ошибок, но ничего не выводит
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,888
23.06.2019, 10:22 4
Добавляйте отладочный вывод на каждом этапе, используйте отладчик. Что тут еще можно посоветовать.
У меня freeBSD нет, ошибка не воспроизводится.
0
0 / 0 / 0
Регистрация: 26.11.2017
Сообщений: 289
23.06.2019, 10:57  [ТС] 5
Вы, случайно, не знаете почему не выводятся размеры файлов?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <algorithm>
 
#include <dirent.h>
 
#include <iostream>
 
#include <stdio.h>
 
#include <string>
 
#include <string.h>
 
#include <sys/stat.h>
 
#include <sys/types.h>
 
#include <vector>
 
bool cmp(std::pair<std::string, int> a, std::pair<std::string, int> b)
 
{
 
return a. second < b. second;
 
}
 
int main(int argc, char* argv[])
 
{
 
DIR* d = opendir(".");
 
if (d == NULL)
 
{
 
perror("Ошибка открытия текущего каталога");
 
}
 
struct dirent* de;
 
std::vector<std::pair<std::string, int>> files; // Сюда будут записаны имена и размеры файлов
 
while (de = readdir(d))
 
{
 
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
 
{
 
continue; // 
 
}
 
struct stat st;
 
if (stat(de->d_name, &st) == -1)
 
{
 
std::cout << "Ошибка stat(" << de->d_name << "): " << strerror(errno) << std::endl;
 
}
 
else
 
{
 
if (S_ISDIR(st. st_mode))
 
{
 
std::cout << de->d_name << std::endl;
 
}
 
else
 
{
 
files. push_back(std::pair<std::string, int>(de->d_name, st. st_size));
 
}
 
}
 
}
 
closedir(d);
 
std::sort(files. begin(), files. end(), cmp);
 
for (int i = 0; i < files. size(); i++)
 
{
 
std::cout << files[i].first << std::endl;
 
}
 
return 0;
 
}
0
23.06.2019, 10:57
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.06.2019, 10:57
Помогаю со студенческими работами здесь

Организация связи один-ко многим
Стоит следующая задача: отобразить связь один ко многим в двух гридах. Для реализации я...

Организация связи многие-ко-многим
Можно ли создать связь многие-ко-многим по аналогу создания один-ко многим... я соединяю по...

организация связи по siemens + GSM + opc
Здравствуйте. помогите разобраться. Нужно организовать связь от ПЛК по GSM на арм сигналы. ПЛК...

Правильная организация связи один ко многим
Здравствуйте, помогите разобратся с возникшей проблемой. Есть база данных (не моя) в ней две...

Организация связи по ethernet на stm32 nucleo-f767zi
Всем привет! Покопав в сторону вопроса организации связи между ПК и платой с МК, а также...

Организация связи между ПЛК Siemens Logo и ПК
могите плиз сам в этой теме впервые имеем ПЛК siemens logo и пк нужно организовать передачу данных...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru