Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/15: Рейтинг темы: голосов - 15, средняя оценка - 4.60
0 / 0 / 0
Регистрация: 02.09.2016
Сообщений: 10

Бесконечный цикл сервера выводящий сообщения

16.06.2017, 15:34. Показов 3307. Ответов 8
Метки нет (Все метки)

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

Вот код сервера:
1)Program
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
using System;
using System.Threading;
 
namespace ChatServer
{
    class Program
    {
        static ServerObject server; // сервер
        static Thread listenThread; // потока для прослушивания
        static void Main(string[] args)
        {
            try
            {
                server = new ServerObject();
                listenThread = new Thread(new ThreadStart(server.Listen));
                listenThread.Start(); //старт потока
            }
            catch (Exception ex)
            {
                server.Disconnect();
                Console.WriteLine(ex.Message);
            }
        }
    }
}
2)ServerObject
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading;
 
namespace ChatServer
{
    public class ServerObject
    {
        static TcpListener tcpListener; // сервер для прослушивания
        List<ClientObject> clients = new List<ClientObject>(); // все подключения
 
        protected internal void AddConnection(ClientObject clientObject)
        {
            clients.Add(clientObject);
        }
        protected internal void RemoveConnection(string id)
        {
            // получаем по id закрытое подключение
            ClientObject client = clients.FirstOrDefault(c => c.Id == id);
            // и удаляем его из списка подключений
            if (client != null)
                clients.Remove(client);
        }
        // прослушивание входящих подключений
        protected internal void Listen()
        {
            try
            {
                tcpListener = new TcpListener(IPAddress.Any, 8888);
                tcpListener.Start();
                Console.WriteLine("Сервер запущен. Ожидание подключений...");
 
                while (true)
                {
                    TcpClient tcpClient = tcpListener.AcceptTcpClient();
 
                    ClientObject clientObject = new ClientObject(tcpClient, this);
                    Thread clientThread = new Thread(new ThreadStart(clientObject.Process));
                    clientThread.Start();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Disconnect();
            }
        }
 
        // трансляция сообщения подключенным клиентам
        protected internal void BroadcastMessage(string message, string id)
        {
            byte[] data = Encoding.Unicode.GetBytes(message);            
            for (int i = 0; i < clients.Count; i++)
            {
                if (clients[i].Id != id) // если id клиента не равно id отправляющего
                {
                    clients[i].Stream.Write(data, 0, data.Length); //передача данных
                }
            }
        }
        // отключение всех клиентов
        protected internal void Disconnect()
        {
            tcpListener.Stop(); //остановка сервера
 
            for (int i = 0; i < clients.Count; i++)
            {
                clients[i].Close(); //отключение клиента
            }
            Environment.Exit(0); //завершение процесса
        }
    }
}
3)ClientObject
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
using System;
using System.Net.Sockets;
using System.Text;
 
namespace ChatServer
{
    public class ClientObject
    {
        protected internal string Id { get; private set; }
        protected internal NetworkStream Stream { get; private set; }
        string userName;
        TcpClient client;
        ServerObject server; // объект сервера
 
        public ClientObject(TcpClient tcpClient, ServerObject serverObject)
        {
            Id = Guid.NewGuid().ToString();
            client = tcpClient;
            server = serverObject;
            serverObject.AddConnection(this);
        }
 
        public void Process()
        {
            try
            {
                Stream = client.GetStream();
                // получаем имя пользователя
                string message = GetMessage();
                userName = message;
 
                message = userName + " вошел в чат";
                // посылаем сообщение о входе в чат всем подключенным пользователям
                server.BroadcastMessage(message, this.Id);
                Console.WriteLine(message);
                // в бесконечном цикле получаем сообщения от клиента
                while (true)
                {
                    try
                    {
                        message = GetMessage();                       
                        message = String.Format("{0}: {1}", userName, message);
                        Console.WriteLine(message);
                        server.BroadcastMessage(message, this.Id);                        
                    }
                    catch
                    {
                        message = String.Format("{0}: покинул чат", userName);
                        Console.WriteLine(message);
                        server.BroadcastMessage(message, this.Id);
                        break;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            finally
            {
                // в случае выхода из цикла закрываем ресурсы
                server.RemoveConnection(this.Id);
                Close();
            }
        }
 
        // чтение входящего сообщения и преобразование в строку
        private string GetMessage()
        {
            byte[] data = new byte[64]; // буфер для получаемых данных
            StringBuilder builder = new StringBuilder();
            int bytes = 0;
            do
            {
                bytes = Stream.Read(data, 0, data.Length);
                builder.Append(Encoding.Unicode.GetString(data, 0, bytes));
            }
            while (Stream.DataAvailable);
 
            return builder.ToString();
        }
 
        // закрытие подключения
        protected internal void Close()
        {
            if (Stream != null)
                Stream.Close();
            if (client != null)
                client.Close();
        }
    }
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
16.06.2017, 15:34
Ответы с готовыми решениями:

IEnumerator функция и бесконечный цикл ожидания ответов от сервера
Добрый день! Есть функция public IEnumerator StartSoket(string status, int connect_id, string url), которая открывает новое соединение...

Как реализовать бесконечный цикл While, но чтобы этот цикл не грузил процессор?
Допустим есть цикл: while (1) { ... } Как сделать так, чтобы бесконечный цикл не грузил процессор. Избавиться от...

Цикл do/while. Страница в браузере, уходит в бесконечный цикл и ничего не выводит.
Помогите, страница в браузере, как я понял, уходит в бесконечный цикл и ничего не выводит. Если переменные без ввода обозначить сразу, то...

8
0 / 0 / 0
Регистрация: 16.06.2017
Сообщений: 20
17.06.2017, 02:15
А где у сервера метод получения сообщений от клиентов?

Добавлено через 11 минут
не увидел сначала метод

Добавлено через 2 минуты
можно добавить проверку перед выводом на экран, но проблему это не решит
0
0 / 0 / 0
Регистрация: 02.09.2016
Сообщений: 10
17.06.2017, 04:25  [ТС]
0012345678900, мне кажется, что проверку нужно вставить в этом месте
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 while (true)
                {
                    try
                    {
                        message = GetMessage();                       
                        message = String.Format("{0}: {1}", userName, message);
                        Console.WriteLine(message);
                        server.BroadcastMessage(message, this.Id);                        
                    }
                    catch
                    {
                        message = String.Format("{0}: покинул чат", userName);
                        Console.WriteLine(message);
                        server.BroadcastMessage(message, this.Id);
                        break;
                    }
                }
Но вот какую я что-то не знаю. По сути циклить он начинает, когда на клиенте закрывается поток, но я правда не знаю, что приходит на сервер, когда на клиенте закрывается поток...
0
0 / 0 / 0
Регистрация: 16.06.2017
Сообщений: 20
17.06.2017, 04:56
можно пожалуйста код клиента? Я просто хочу проверить работу сервера и клиента
0
0 / 0 / 0
Регистрация: 02.09.2016
Сообщений: 10
17.06.2017, 16:12  [ТС]
0012345678900, вот клиент
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
 
namespace WindowsFormsApp1
{
    class Program
    {
        public static string userName;
        public static string host;
        private const int port = 8888;
        static TcpClient client;
        public static NetworkStream stream;
        public static Boolean ExitApp = true;
        public static Form1 loginForm;
        public static Form2 chatForm;
 
        /// <summary>
        /// Главная точка входа для приложения.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            loginForm = new Form1();
            chatForm = new Form2();
            loginForm.ShowDialog();
           
        }
 
        //Соединение с сервером
 
        public static void ConServ()
        {
            client = new TcpClient();
            try
            {
                client.Connect(host, port); //подключение клиента
                stream = client.GetStream(); // получаем поток
 
                string message = userName;
                byte[] data = Encoding.Unicode.GetBytes(message);
                stream.Write(data, 0, data.Length);
 
                 //запускаем новый поток для получения данных
                Thread receiveThread = new Thread(new ThreadStart(ReceiveMessage));
                receiveThread.Start();//старт потока 
                receiveThread.IsBackground = true;
 
 
            }
            catch (Exception ex)
            {
                
                chatForm.textBox1.Text += "Не удалось подключиться к серверу.";
                chatForm.textBox1.Text += "\r\n" + ex.Message + "\r\n";               
 
                if (MessageBox.Show("Хотите снова соединиться с сервером?", "Ошибка подключения к серверу", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    ExitApp = false;
                    Application.Restart();
                }
                else
                {
                    Disconnect();
                }
            }
            
        }
 
 
        // отправка сообщений
         public static void SendMessage(string message)
        {
            byte[] data = Encoding.Unicode.GetBytes(message);
            stream.Write(data, 0, data.Length);                        
 
        }
        // получение сообщений
        static void ReceiveMessage()
        {
            Boolean error = true;
            while(error == true) {
                try
                {
                    byte[] data = new byte[64]; // буфер для получаемых данных
                    StringBuilder builder = new StringBuilder();
                    int bytes = 0;
                    do
                    {
                        bytes = stream.Read(data, 0, data.Length);
                        builder.Append(Encoding.Unicode.GetString(data, 0, bytes));
                    }
                    while (stream.DataAvailable);
 
                    string message = builder.ToString();
                    chatForm.textBox1.Invoke(new Form2.Form2Text1((s) => chatForm.SetTextSafeForm2Text1(s + "\r\n")), message);
                    
                }
                catch
                {
                    chatForm.textBox1.Invoke(new Form2.Form2Text1((s) => chatForm.SetTextSafeForm2Text1(s + "\r\n")), "\r\n" + "Подключение прервано!");
                    //chatForm.textBox1.Text += "\r\n";
                    //chatForm.textBox1.Text += "Подключение прервано!"; //соединение было прервано                    
                    //Disconnect();
                    error = false;
                    if (MessageBox.Show("Хотите снова соединиться с сервером?", "Ошибка соединения", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        ExitApp = false;
                        Application.Restart();                        
                    }
                    else
                    {
                        Disconnect();
                    }
                        
 
                }
            }
        }
 
        public static void Disconnect()
        {          
            //if (stream != null)
            // stream.Close(); //отключение потока
            //if (client != null)
            // client.Close(); //отключение клиента
            //завершение процесса
 
            Environment.Exit(0);
        }
    }
}
Если расскоментить Disconnect, то как раз будет это зацикливание.
0
0 / 0 / 0
Регистрация: 02.09.2016
Сообщений: 10
17.06.2017, 19:21  [ТС]
Вот сами проги.
Вложения
Тип файла: rar WindowsFormsApp1.rar (29.9 Кб, 2 просмотров)
Тип файла: rar Сервер.rar (19.0 Кб, 2 просмотров)
0
0 / 0 / 0
Регистрация: 02.09.2016
Сообщений: 10
18.06.2017, 13:55  [ТС]
Вот какая проверка должна быть, чтобы сервер не циклился.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 while (true)
                {
                    try
                    {
                        message = GetMessage();
                        if (message != "")
                        {
                            message = String.Format("{0}: {1}", userName, message);
                            Console.WriteLine(message);
                            server.BroadcastMessage(message, this.Id);
                        }
                        else
                        {
                            message = String.Format("{0}: покинул чат", userName);
                            Console.WriteLine(message);
                            server.BroadcastMessage(message, this.Id);
                            break;
                        }
                    }
                  }
0
Эксперт .NET
 Аватар для Usaga
14314 / 9399 / 1355
Регистрация: 21.01.2016
Сообщений: 35,436
18.06.2017, 14:26
Folman, откуда вы взяли такие названия: ClientObject, ServerObject? Уже не первый раз такое встречаю. Это какой-то учебник или статья?
0
0 / 0 / 0
Регистрация: 02.09.2016
Сообщений: 10
19.06.2017, 00:43  [ТС]
Usaga, да, вот эта https://metanit.com/sharp/net/4.4.php
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
19.06.2017, 00:43
Помогаю со студенческими работами здесь

Почему цикл на при 1 уходит в бесконечный цикл?
#define _CRT_SECURE_NO_WARNINGS #include &lt;iostream&gt; #include &lt;stdio.h&gt; #include &lt;string.h&gt; int main() { int x=0, y=0,...

Цикл выводящий изображения
В рамках курсовой работы мне нужно написать приложение на языке JAVA с громким названием &quot;ИС для оценки остроты зрения&quot;. На...

Бесконечный цикл While
Здравствуйте, помогите пожалуйста с задачей. Условие - ввести массив, состоящий из х числа элементов, затем &quot;распаковать&quot; его в...

бесконечный цикл
Когда пытаюсь считать строки из файла с помощью цикла, он почему то начинает повторятся бесконечно. Вот код: int main(int argc, char*...

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


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru