Рейтинг темы:
  • 0 Голос(ов) - 0 в среднем
  • 1
  • 2
  • 3
  • 4
  • 5
С# клиент-сервер
#1
Доброго времени суток, господа. Есть ли у кого готовое решение на с# для получения и отправки информации, где одно приложение сервер-распространитель, а другое - клиент(-ы)? Искал, гуглил, читал на хабре, киберфоруме, и даже книжечку. Но видимо, ума не хватает.
Код:
static void Main(string[] args)
        {
            Data.Connect = "Database=bdworld;Data Source=localhost;User Id=root;Password=root";
            TcpListener server = null;
            try
            {              
                int MaxThreadsCount = Environment.ProcessorCount * 4;
                Console.WriteLine(MaxThreadsCount.ToString());
                // Максимальное количество рабочих потоков
                ThreadPool.SetMaxThreads(MaxThreadsCount, MaxThreadsCount);
                // Минимальное количество рабочих потоков
                ThreadPool.SetMinThreads(2, 2);


                // Порт для TcpListener = 9595.
                Int32 port = 9595;
                IPAddress localAddr = IPAddress.Parse("127.0.0.1");
                int counter = 0;
                server = new TcpListener(localAddr, port);
                
                    Data.parse_skills();
                
                // Запускаем TcpListener и начинаем слушать клиентов.
                server.Start();

                // Принимаем клиентов в бесконечном цикле.
                while (true)
                {
                    Console.Write("\nWaiting for a connection... ");
                    // При появлении клиента добавляем в очередь потоков его обработку.
                    ThreadPool.QueueUserWorkItem(ObrabotkaZaprosa, server.AcceptTcpClient());  
                }
            }
            catch (SocketException e)
            {
                //В случае ошибки, выводим что это за ошибка.
                Console.WriteLine("SocketException: {0}", e);
            }
            finally
            {
                // Останавливаем TcpListener.
                server.Stop();
            }
        }

В обработке запросов(ObrabotkaZaprosa):
Код:
static void ObrabotkaZaprosa(object client_obj)
        {
            try
            {
                // Буфер для принимаемых данных.
                Byte[] bytes = new Byte[256];
                String data = null;

                //Можно раскомментировать Thread.Sleep(1000);
                //Запустить несколько клиентов
                //и наглядно увидеть как они обрабатываются в очереди.
                //Thread.Sleep(1000);

                Data.client = client_obj as TcpClient;

                data = null;

                // Получаем информацию от клиента
                Data.stream = Data.client.GetStream();

                int i;

                // Принимаем данные от клиента в цикле пока не дойдём до конца.
                while ((i = Data.stream.Read(bytes, 0, bytes.Length)) != 0)
                {
                    // Преобразуем данные в ASCII string.
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);

                    //В handling switch с определением что за сообщение, обработка его и возврат ответа в дату.
                    data = Data.handling(data);

                    // Преобразуем полученную строку в массив Байт.
                    byte[] msg = System.Text.Encoding.ASCII.GetBytes(data);

                    try
                    {
                        // Отправляем данные обратно клиенту (ответ).
                        Data.stream.Write(msg, 0, msg.Length);
                    }
                    catch (Exception err)
                    { Console.WriteLine(err.ToString()); }

                }

                // Закрываем соединение.
                Data.client.Close();
            }
            catch { }

        }

Самое неприятное, что при очень быстром количестве запросов от клиента(раз в 100 мс) - сервер выпадает не удосужившись толком обьяснить в чём дело, ссылается на то, что было обращение к уже уничтоженным обьектам(самым разным). Может есть у кого готовое решение? Не могу до конца понять, как же всё-таки должен сервер общаться с клиентами. Код ужасен, помидорами кидайте, но помогите плс))
Ответ
#2
Зачем обращения раз в 100 мс?
[Изображение: 4e38c909fcd08c5fcdf363b54a62.png]
Ответ
#3
Раз в 100 мс узнаю, есть ли новые сообщения для клиента. (чат, список игроков, к примеру)
Ответ
#4
Если вы решили писать на C# - я бы предложил вам - взять за основу, кое что другое
пример контента
Эмулятор полностью функционален, но заточен немного под другую игру, сама игра очень схоже по структуре с L2, ввиду того что использует движок почти той же версии что и L2, отсюда все(пакеты, игровой мир и прочее - не слишком разные)
Я правда не полностью уверен что там именно C#, возможно там C++ , и что-то от C#, но в любом случае это сурс - и может быть более удобной базой для разработки, по крайней мере не все нужно будет писать с нуля.
Ответ
#5
DrHolmes Написал:Если вы решили писать на C# - я бы предложил вам - взять за основу, кое что другое
пример контента
Эмулятор полностью функционален, но заточен немного под другую игру, сама игра очень схоже по структуре с L2, ввиду того что использует движок почти той же версии что и L2, отсюда все(пакеты, игровой мир и прочее - не слишком разные)
Я правда не полностью уверен что там именно C#, возможно там C++ , и что-то от C#, но в любом случае это сурс - и может быть более удобной базой для разработки, по крайней мере не все нужно будет писать с нуля.

А можно ссылочку? Если вы не против?

Нашёл решение(моя ошибка в создании нового подключения при каждом запросе, что вызывало ессно исключение, если подключение было в параллельном потоке закрыто(а обьект подключения статический)). И всё-таки, пока занимаюсь программирования - начинаю верить в "коллективный разум"! Уже не 1 и не 2 раза как замечаю. Только задаю вопрос знающим людям - через короткое время ответ приходит сам в голову, хотя до этого мог день возиться ошибкой. Будь-то не одна голова думала, будь-то ещё "приплюсовались процессоры", думающих над моим вопросом людей. Удивительно, но факт. Кому интерестно, сама суть ошибки:
ПРИМЕР ОДНОГО ИЗ ОБРАБОТЧИКОВ сообщения клиентом на отправку(получение сообщений в чат от сервера)

public static void GetChat()
{
TcpListener server = null;
try
{
while (true)
{
try
{
// Создаём TcpClient.
// Для созданного в предыдущем проекте TcpListener
// Настраиваем его на IP нашего сервера и тот же порт.

//Int32 port = 9595;
Data.client = new TcpClient(Data.server, Data.port);

// Переводим наше сообщение в ASCII, а затем в массив Byte.
Byte[] data = System.Text.Encoding.ASCII.GetBytes("(%3)" + Data.key);

// Получаем поток для чтения и записи данных.
Data.stream = Data.client.GetStream();

// Отправляем сообщение нашему серверу.
Data.stream.Write(data, 0, data.Length);
//Console.WriteLine("Sent: {0}", message);

// Получаем ответ от сервера.

// Буфер для хранения принятого массива bytes.
data = new Byte[256];

// Строка для хранения полученных ASCII данных.
String responseData = String.Empty;

// Читаем первый пакет ответа сервера.
// Можно читать всё сообщение.
// Для этого надо организовать чтение в цикле как на сервере.
Int32 bytes = stream.Read(data, 0, data.Length);
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
//Console.WriteLine("Received: {0}", responseData);
// Закрываем всё.
Data.stream.Close();
Data.client.Close();
if ((!responseData.Contains("hui")) && (responseData.Contains("(%3)")))
{
OPdata = new string[16, 100000];
responseData = responseData.Replace("(%3)", "");
/*string nick="";
for (int i = 0; i < responseData.Length; i++)
{
if (responseData[i] == '!')
{
nick = responseData.Remove(i);
Data.Chat.Add(responseData.Remove(0, nick.Length));
break;
}
}*/
Data.Chat.Add(responseData);
}

}
catch { }
Thread.Sleep(100);
}
}
catch { }
}


Если данную ф-цию послать на выполнение в поток(и рядом в потоке подобную), то Data.client = new TcpClient(Data.server, Data.port); клиент вроде как будет пытаться сработать, но в отладчике уже будет видно готовое исключение для Data.stream = Data.client.GetStream(); Поэтому подключиться надо было всего один раз, при коннекте пользователя, после чего указанные строки удалить из других ф-ций. Спасибо, уважаемые форумчане! Коллективный разум решает!))
Ответ
#6
kpNemo Написал:Раз в 100 мс узнаю, есть ли новые сообщения для клиента. (чат, список игроков, к примеру)
Раз 1-5 секунд вполне достаточно. Или вообще делать on event (при добавлении нового игрока в список идет пакет).
[Изображение: 4e38c909fcd08c5fcdf363b54a62.png]
Ответ
#7
Предлагаю попробовать фреймворк Scs, _https://github.com/hikalkan/scs не реклама, удобная сеть, подходит как для серверной так и для клиентской части.
Ответ
#8
Smile мне вот интересно вы выбрали C# чисто из за знания данного языка или по каким то другим соображениям? Просто для меня имхо из C - C++ более адекватен...
У меня есть только два чувства, похмелье и изжога.
Ответ
#9
Sisi Написал:Smile мне вот интересно вы выбрали C# чисто из за знания данного языка или по каким то другим соображениям? Просто для меня имхо из C - C++ более адекватен...

Работаю на с# на постоянной основе на дядю(разработка ПО для ВУЗов Украины и России) чуть больше года всего-то навсего, с++ знал, но год его не видел и позабыл аж не хочется вспоминать.
Ответ


Возможно похожие темы ...
Тема Автор Ответы Просмотры Последний пост
  Загрузка armor.grp в веб клиент пару вопросов OneThunder 8 2,190 07-30-2016, 11:00 PM
Последний пост: OneThunder
  c# клиент-сервер kpNemo 1 2,209 03-22-2016, 10:38 AM
Последний пост: PROGRAMMATOR
  Основы клиент - серверных приложений OneThunder 12 4,296 01-20-2016, 07:18 PM
Последний пост: Dambenok
  Git сервер Virt 6 1,989 09-08-2014, 06:40 PM
Последний пост: OneThunder
  Выбор СУБД под Java сервер Ramzessuss 10 7,761 08-05-2010, 08:06 AM
Последний пост: pitch

Перейти к форуму:


Пользователи, просматривающие эту тему: 2 Гость(ей)