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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Создание Списка активных соединений на сервере, Sockets 
:(
    Опции темы
tshadrin
Дата 15.10.2009, 04:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте, проблема такая:
есть сервер, который ждет соединения. 
Когда соеденяется клиент создается объект класса для асинхронной работы с клиентом, который получает ссылку на соединение.
С соединениями все в полном порядке, с отправкой сообщений от сервера к клиенту и обратно все хорошо.
Задача:
1.Сделать список активных клиентов(т.е. тех которые в данный момент соеденены) (получилось на примере ниже)
2.Постоянно знать число активных клиентов.(в общем то получилось, но при отклюении клиента нужно будет сортировать массив
иначе может быть 2 клиента с uid 2 и т.п.
3.Как в данном классе сделать так чтобы полученное сообщение от одного клиента отсылалось всем клиентам из массива сокетов класса Users. Как сделать так, чтобы собщение отправлялось определенному клиенту?

Что пробовал:
Создать класс для обработки каждого входящего соединения.

Код

public class Users
{
    //Идентификатор пользователя
    private int uid;
    //Список сокетов подключенных пользователей;
    public Socket[] clients = Socket[];
    private static int numOfUsers = 0;
    public Users(Socket handler)
    {
        //присваиваем клиенту uid равный количеству клиентов +1
        numOfUsers++;
        uid = numOfUsers;
        //Записываем дескриптор соединения клиента в массив клиентских сокетов.
    clients[uid] = handler;
        //Создаем объект класса для работы с текущим соединением, который выглядит примерно так:
        ClientMSG clmsg = new ClientMSG(handler, uid);
    }   
}
class ClientMSG 
{
    private int uid;
    private Socket handler;
    private byte[] bytes = new byte[1024];
    private byte[] buffer = new byte[1024];
    string content = String.Empty;
    public ClientMSG(Socket handler, int uid) 
    {
        thisUser = App.users[uid];
        this.uid = uid;
    this.handler = handler; 
        Console.WriteLine("Соединение {0} установлено", uid);
    handler.BeginReceive(buffer, 0, buffer.Length, 0, new AsyncCallback(ReceiveCallBack), handler);
    } 

    public void ReceiveCallBack(IAsyncResult ar)
    {
        Socket handler = (Socket) ar.AsyncState;
        int bytesRead = handler.EndReceive(ar);
        if(bytesRead > 0)
    {
        content += Encoding.ASCII.GetString(buffer, 0, bytesRead);
        }
        if(content.IndexOf("\r\n") > -1)
        { 
        Console.WriteLine("Прочитано {0} байтов от сокета. Данные: {1}", content.Length, content);
            content = null;
            handler.BeginReceive(buffer, 0, buffer.Length, 0, new AsyncCallback(ReceiveCallBack), handler);
    }
    else
    {
        handler.BeginReceive(buffer, 0, buffer.Length, 0, new AsyncCallback(ReceiveCallBack), handler);
    }

    }
} 


Заранее спасибо за ответы. На c# пытаюсь писать 3 день. Читаю Троелсона: C# 2005 и платформа .NET 2.0. (дошел до главы про делегаты и события).
Что порекомендуете почитать, чтобы самому найти решение?



Это сообщение отредактировал(а) tshadrin - 15.10.2009, 04:08
PM MAIL   Вверх
tshadrin
Дата 23.10.2009, 03:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



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

Алгоритм:
Клиент посылает информацию о себе на сервер такого вида:
1.Ник
2.Статус
3....
Сервер добавляет в массив пользователей новую запись.
Клиент после отправки запроса с именем пользователя посылает команду серверу на получение списка пользователей, и их статуса.
И посылает этот запрос на сервер через каждую к примеру секунду.
Для получения сообщения адресованного всем пользователям есть своя строковая переменная содержащая последнее сообщение.
В небольшой промежуток времени сервер посылает запрос на получение последнего сообщения, которое имеет вид типа
Ник+сообщение, которое отображается на клиенте.
Также клиент может послать другому клиенту на сервере сообщение которое будет приватным.
Соответственно для каждого клиента должна быть строка содержащая последнее приватное сообщение.
Запрос на наличие новых данных в этой строке также посылают клиенты раз к примеру в 20мс.

Проблемы которые вижу при использовании данного алгоритма - Сильная нагрузка запросами на сервер.
К сожалению другого варианта для разгрузки сервера пока не нахожу. 
Не понятен к примеру вопрос - как оповестить пользователей о том что кто-то вышел из чата?

Это сообщение отредактировал(а) tshadrin - 23.10.2009, 03:05
PM MAIL   Вверх
Exai1e
Дата 23.10.2009, 03:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата(tshadrin @  23.10.2009,  04:02 Найти цитируемый пост)
Не понятен к примеру вопрос - как оповестить пользователей о том что кто-то вышел из чата?

ну посылай команду:
ник
команда

где команда - например (подключился, запрашивает какую либо инфу с сервера, вышел)
а при отключении, когда посылаеш команду (ВасяПупкин - командаОтключился) сервер отсылает ник отключившегося клиента всем клиентам и клиенты узнают что клиент с ником ВасяПупкин отключился - это как вариант.

Я бы сделал по другому - примерно так, но посылал бы не текстовые данные (не строку) а объект (почитам в той же клинже про сериализацию). Сделай класс к примеру
под рукой студии нет, я образно покажу:
Код

[Serializable]
Класс МоеСообщение
{
  string command; //где команда будет либо в числовом, либо в строковом варианте - например 
  "1" - отключился
  "2" - подключился
  "3" - запросил... к примеру время с сервера
  
  string text; //текст сообщения

  set, get, etc.
}


и как то так , когда отключаешся будет использовать
Код

МоеСообщение my = new МоеСообщение();

//когда клиент отключается
my.command = 1;
my.text = myNickName;
//запихиваеш объект в поток, и отсылаеш


на сервере, при приеме сообщения, получаеш объект из потока и какимнить case проверяеш команду
принял, десериализовал и передал значение команды)
Код

case (myObject.command)
{
  1 : полслал сообщение всем клиентам что клиент отключился
 2 : послал всем команду что клиент подключился и они к примеру же, могут добавить его в свой список активных клиентов
и т.д.
}


Как то примерно так, класс "сообщение" можно напихать доп свойствами по усмотрению.
зы. голова не варит в пол пятого, но общая картина думаю ясна

Это сообщение отредактировал(а) Exai1e - 23.10.2009, 03:34


--------------------
"Решение зависит от выбранного геморроя" © Snowy
"у нас как в армии - либо работает, либо так и задумано"
PM MAIL ICQ   Вверх
tshadrin
Дата 23.10.2009, 23:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Дело в том что у меня никак не получается реализовать рассылку сообщения всем подключенным клиентам.
Я интуитивно конечно догадался что стоит использовать массив сокетов при входящем соединении:
Код

Socket clients[] = new Socket;
clients.[clients.Length] = server.Accept();

Но вопрос остался такой: как правильно индексировать массив и рассылать данные с использованием асинхронных методов и калбеков?

В общем можно небольшой пример отправки сообщения нескольким клиентам? Буду благодарен, да и дело сдвинется.

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

Это сообщение отредактировал(а) tshadrin - 23.10.2009, 23:50
PM MAIL   Вверх
Exai1e
Дата 24.10.2009, 11:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Цитата

Серверная часть:
1. Основной класс твоего сервера, который создает объект серверного сокета и ожидает в основном цикле подключения клиентов-сокетов, обрабатывает подключение новых клиентов.
2. Класс, отвечающий за взаимодействие между клиентом и сервером, пересылку сообщений клиенту и т.д.
3. Массив объектов классов (из п. 2) подключенных клиентов.
Клиентская часть:
1. Основной класс твоего клиента, отвечающий за подключение к серверу и принятие/передачу данных от/к серверу.
Алгоритм работы серверной части системы:
1. Создаешь объект основного класса твоего сервера, в котором создается сервер-сокет и далее в основном цикле ожидаешь подключения клиентов-сокетов.
2. При подключении нового клиента-сокета — обрабатываешь это радостное событие, а именно:
2.1. Создаешь объект класса, отвечающего за взаимодействие сервера с клиентом (допустим в качестве параметра в конструктор передаешь сокет-клиент, подключение которого ты обрабатываешь).
2.2. Создаешь отдельный поток для подключившегося клиента и передаешь этому потоку объект класса, созданный в п. 2.1.
2.3. Добавляешь в массив экземляров классов подключенных клиентов новый объект.
Дальше — по вкусу! 

© стырено с другого форума


--------------------
"Решение зависит от выбранного геморроя" © Snowy
"у нас как в армии - либо работает, либо так и задумано"
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
cully
mr.DUDA
Exception

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, cully, mr.DUDA, Exception.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Распределённые приложения и сеть | Следующая тема »


 




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


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

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