Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сокеты. Как правильно написать сервер? 
:(
    Опции темы
sofen
Дата 28.5.2012, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 26.5.2011

Репутация: нет
Всего: нет



Поясните, плиз, как правильно написать сервер для работы с несколькими клиентами через сокеты (с++, линукс) ?
PM MAIL   Вверх
boostcoder
Дата 28.5.2012, 14:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(sofen @  28.5.2012,  13:52 Найти цитируемый пост)
с++

например так: http://code.google.com/p/netclasses/source...ver/server2.cpp
PM WWW   Вверх
baldina
Дата 28.5.2012, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: нет
Всего: 101



http://www.proklondike.com/books/unix/robachevsky_unix.html

а если кратко, после каждого соединения нужно отдавать обработку отдельному потоку или процессу, что бы освободить поток, слушающий на порту. иначе другие клиенты, кроме текущего, не смогут подсоединиться.
с другой стороны, нужно использовать неблокирующие функции типа select, epool, iocp.
в C++ есть высокоуровневые библиотеки, скрывающие всю эту мутотень внутри, напр. boost::asio
PM MAIL   Вверх
boostcoder
Дата 28.5.2012, 14:44 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



по той ссылке что я привел, 'struct server_impl' правильней назвать session. ибо это объект сессии создаваемый сервером для каждого входящего соединения.
каждый такой объект, имеет ссылку на 'struct global_context', в которой реализована глобальная логика + глобальные данные.

так, к примеру, несколько недель назад, на базе этого набора классов, написал мессенждевую сеть для некой конторы, за два дня. с авторизацией+логами+списком контактов+групповой рассылкой smile 
и то, больша часть времени ушла на гуй.


Это сообщение отредактировал(а) boostcoder - 28.5.2012, 14:47
PM WWW   Вверх
sofen
Дата 28.5.2012, 14:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 26.5.2011

Репутация: нет
Всего: нет



Цитата(baldina @ 28.5.2012,  12:22)
http://www.proklondike.com/books/unix/robachevsky_unix.html

а если кратко, после каждого соединения нужно отдавать обработку отдельному потоку или процессу, что бы освободить поток, слушающий на порту. иначе другие клиенты, кроме текущего, не смогут подсоединиться.
с другой стороны, нужно использовать неблокирующие функции типа select, epool, iocp.
в C++ есть высокоуровневые библиотеки, скрывающие всю эту мутотень внутри, напр. boost::asio

boost - это, конечно, интересно, но хотел разобраться в самом механизме...

вот здесь http://www.rsdn.ru/article/unix/sockets.xml нашёл следующий код сервера

Код

int main()
{
    int sock, listener;
    struct sockaddr_in addr;
    char buf[1024];
    int bytes_read;

    listener = socket(AF_INET, SOCK_STREAM, 0);
    if(listener < 0)
    {
        perror("socket");
        exit(1);
    }
    
    addr.sin_family = AF_INET;
    addr.sin_port = htons(3425);
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    if(bind(listener, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    {
        perror("bind");
        exit(2);
    }

    listen(listener, 1);
    
    while(1)
    {
        sock = accept(listener, NULL, NULL);
        if(sock < 0)
        {
            perror("accept");
            exit(3);
        }

        while(1)
        {
            bytes_read = recv(sock, buf, 1024, 0);
            if(bytes_read <= 0) break;
            send(sock, buf, bytes_read, 0);
        }
    
        close(sock);
    }
    
    return 0;
}


получается так:

1. вначале создаём listener - слушающий сокет
2. потом sock - сокет для получения/передачи данных
3. читаю сервером данные, обрабатываю и отсылаю ответ

и теперь возникают непонятки - зачем закрывать сокет?  

close(sock); 

и потом опять его создавать, переходя по циклу while (1) ?

sock = accept(listener, NULL, NULL);
PM MAIL   Вверх
boostcoder
Дата 28.5.2012, 14:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(sofen @  28.5.2012,  14:53 Найти цитируемый пост)
хотел разобраться в самом механизме

увольте. я не могу такое объяснять smile 
даже заметку по этому поводу написал. эх...закончить бы ее еще..

Добавлено через 12 минут и 3 секунды
ладно...
Цитата(sofen @  28.5.2012,  14:53 Найти цитируемый пост)
зачем закрывать сокет?

до строки закрытия сокета программа досдет только в случае обрыва соединения. а если соединение оборвалось, зачем держать сокет открытым?

Цитата(sofen @  28.5.2012,  14:53 Найти цитируемый пост)
и потом опять его создавать, переходя по циклу while (1) ?

потому что переходя к началу цикла, программа остановится на аксепте в ожидании нового подключившегося. и после его подключения, снова начнется чтение/запись в/из сокета.

PM WWW   Вверх
baldina
Дата 28.5.2012, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: нет
Всего: 101



Цитата(sofen @  28.5.2012,  14:53 Найти цитируемый пост)
хотел разобраться в самом механизме

читайте Робачевского, там все просто и понятно.

Цитата(sofen @  28.5.2012,  14:53 Найти цитируемый пост)
зачем закрывать сокет

Цитата

Это приведёт к разрыву соединения

accept - прием запроса на соединение (от очередного клиента)
пример этого эхо-сервера - простейший, он обслуживает только одного клиента в единицу времени.

Добавлено через 13 минут и 41 секунду
Цитата(sofen @  28.5.2012,  14:53 Найти цитируемый пост)
получается так:

1. вначале создаём listener - слушающий сокет
2. потом sock - сокет для получения/передачи данных
3. читаю сервером данные, обрабатываю и отсылаю ответ

не совсем.
1. socket() - создаем сокет как набор параметров соединения (протокол, тип)
2. bind() - связываем его с сервером (т.е. захватываем ресурс в нашей системе) - адрес, порт
3. listen() - инициируем процесс "прослушивания" входящих соединений
для очередного входящего соединения (инициированного клиентом)
4. accept() - принимаем запрос на соединение [пакет с флагом SYN], с этого момента соединение установлено
5. read/write читаем/пишем в стиле обычного файлового ввода/вывода [пакеты с флагом SYN-ASK/ASK]
6. close() - закрываем соединение, соединение разрывается [пакет с флагом FIN]
PM MAIL   Вверх
baldina
Дата 28.5.2012, 15:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: нет
Всего: 101



Цитата(baldina @  28.5.2012,  15:09 Найти цитируемый пост)
4. accept() - принимаем запрос на соединение [пакет с флагом SYN], с этого момента соединение установлено
5. read/write читаем/пишем в стиле обычного файлового ввода/вывода [пакеты с флагом SYN-ASK/ASK]
6. close() - закрываем соединение, соединение разрывается [пакет с флагом FIN] 

accept возвращает дескриптор (socket) - аналог дескриптора файла
PM MAIL   Вверх
sofen
Дата 28.5.2012, 16:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 26.5.2011

Репутация: нет
Всего: нет



Цитата

читайте Робачевского, там все просто и понятно.


ок, читаю...  у него в книжке есть пример, возможно, решение моей задачи - попробую реализовать... посмотрим, что получиться...
PM MAIL   Вверх
boostcoder
Дата 28.5.2012, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 13
Всего: 110



Цитата(sofen @  28.5.2012,  16:05 Найти цитируемый пост)
решение моей задачи

а разве где-то в теме озвучена ваша задача? оО

Добавлено через 32 секунды
перечитал тему еще раз. и правда, нигде не озвучена.
а телепаты нынче в дефиците.
PM WWW   Вверх
baldina
Дата 28.5.2012, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: нет
Всего: 101



Цитата(boostcoder @  28.5.2012,  14:56 Найти цитируемый пост)
до строки закрытия сокета программа досдет только в случае обрыва соединения.

только в данном случае, т.е. только в паре с данным клиентом
в общем случае она туда доедет и просто в случае конца файла.
и тогда инициатором разрыва будет сервер, а не клиент.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0764 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.