Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163

Клиент-Серверное приложение: как отсоединиться от сервера

05.09.2012, 16:43. Показов 2362. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Клиент на C#
Сервер на ANSI-C

Сервер подаёт структуры размером в 38байт.
Клиент Получает Байты и чз BitConverter я получаю свои данные(пробовал чз Маршал оказалось слишком долго, пробовал чз Unsafe-код с применением fixed оказалось не важно почему-то встаёт поток колом будто буфер переполняется где то и данные застывают)
я вывожу данные в Textbox.чз Бесконечный цикл.Данные выводятся всё нормально.
Но вопрос делетанский как отсоединится от сервера?
У меня есть кнопка-Коннект, нажимаю данные пошли.но после нажатия форма не активна.хочу сделать что бы при повторном нажатие происходил дисконнект. Что мне нужно для этого сделать
Код Клиента.


Добавлено через 57 минут
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
public void Connect(String server, Int32 port)
        {
            byte[] buf12 = new byte[8048];
            TcpClient client = null;
            NetworkStream networkStream = null;
            //client.NoDelay = false;
            client = new TcpClient(server, port);
            networkStream = client.GetStream();
            int k = 0;
            while(true)
            try
            {
                button1.Enabled = true;
                buf12 = new byte[8048];
                //Подключение к серверу
 
                int read = networkStream.Read(buf12, 0, buf12.Length);
                k++;
                for (int i = 40; i <= read; i = i + 40)
                {
                    textBox1.AppendText("\n" + BitConverter.ToInt16(buf12, i - 8).ToString() + "\n");
                    table.Rows[0].Cells[1].Value = BitConverter.ToSingle(buf12, i - 40);
                    table.Rows[1].Cells[1].Value = BitConverter.ToSingle(buf12, i - 36);
                    table.Rows[2].Cells[1].Value = BitConverter.ToSingle(buf12, i - 32);
                    table.Rows[3].Cells[1].Value = BitConverter.ToSingle(buf12, i - 28);
                    table.Rows[4].Cells[1].Value = BitConverter.ToSingle(buf12, i - 24);
                    table.Rows[5].Cells[1].Value = BitConverter.ToSingle(buf12, i - 20);
                    table.Rows[6].Cells[1].Value = BitConverter.ToInt16(buf12, i - 16);
                    table.Rows[7].Cells[1].Value = BitConverter.ToSingle(buf12, i - 12);
                    table.Rows[8].Cells[1].Value = BitConverter.ToInt16(buf12, i - 8);
                    table.Rows[9].Cells[1].Value = BitConverter.ToInt16(buf12, i - 6);
                    table.Rows[10].Cells[1].Value = BitConverter.ToInt16(buf12, i - 4);
                }
                textBox1.AppendText("\n");
               // client.Close();
            }
            // ошибка соединения
            catch (Exception e)
            {
                MessageBox.Show(e.Message.ToString());
                client.Close();
            }
        }
Добавлено через 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
private void button1_Click(object sender, EventArgs e)
        {
            Thread _t = new Thread(new ThreadStart(Connect));
            _t.IsBackground = true;
            _t.Start();
            
        }
       
                private void Connect()
        {
            String server = "192.168.10.100";
            Int32 port = 6000;
            byte[] buf12 = new byte[8048];
            TcpClient client = null;
            NetworkStream networkStream = null;
            //client.NoDelay = false;
            client = new TcpClient(server, port);
            networkStream = client.GetStream();
            int k = 0;
            while(true)
            try
            {
                button1.Enabled = true;
                buf12 = new byte[8048];
                //Подключение к серверу
 
                int read = networkStream.Read(buf12, 0, buf12.Length);
                k++;
                for (int i = 40; i <= read; i = i + 40)
                {
                    //MethodInvoker mi = delegate { textBox1.AppendText("\n" + BitConverter.ToInt16(buf12, i - 8).ToString() + "\n"); };
                    //textBox1.Invoke(mi);
                    //textBox1.AppendText("\n" + BitConverter.ToInt16(buf12, i - 8).ToString() + "\n");
                    table.Rows[0].Cells[1].Value = BitConverter.ToSingle(buf12, i - 40);
                    table.Rows[1].Cells[1].Value = BitConverter.ToSingle(buf12, i - 36);
                    table.Rows[2].Cells[1].Value = BitConverter.ToSingle(buf12, i - 32);
                    table.Rows[3].Cells[1].Value = BitConverter.ToSingle(buf12, i - 28);
                    table.Rows[4].Cells[1].Value = BitConverter.ToSingle(buf12, i - 24);
                    table.Rows[5].Cells[1].Value = BitConverter.ToSingle(buf12, i - 20);
                    table.Rows[6].Cells[1].Value = BitConverter.ToInt16(buf12, i - 16);
                    table.Rows[7].Cells[1].Value = BitConverter.ToSingle(buf12, i - 12);
                    table.Rows[8].Cells[1].Value = BitConverter.ToInt16(buf12, i - 8);
                    table.Rows[9].Cells[1].Value = BitConverter.ToInt16(buf12, i - 6);
                    table.Rows[10].Cells[1].Value = BitConverter.ToInt16(buf12, i - 4);
                }
                //textBox1.AppendText("\n");
               // client.Close();
            }
            // ошибка соединения
            catch (Exception e)
            {
                MessageBox.Show(e.Message.ToString());
                client.Close();
            }
        }// end connection
    }
Добавлено через 52 секунды
Проблема теперь с TextBox'ом Пишет Недопустимая операция в нескольких потоках. =(

Добавлено через 13 минут
C#
1
2
                    Action action = () => textBox1.Text = ("\n" + BitConverter.ToInt16(buf12, i - 8).ToString() + "\n");
                    textBox1.Invoke(action);
Не помогает.
Когда навожу на закрытие формы нажимаю на ЛКМ и удерживаю её то происходит чёрти что(на форме есть DataGridView в ней пишутся значения которые получается Клиент от Сервера.так вот значения начинают "прыгать" построкам и т.д.) но потом нормализуется. Почему так происходит?и как мне это исправить?и как мне сделал вывод в ТекстБокс

Добавлено через 2 часа 44 минуты
Подскажите пожалуйста как правильно "закрыть поток"?
я предполагаю что надо подать на сервер значение "закрыть соединение"?
потом закрыть у себя соединение. и тогда поток сам закроется?а за ним и основной можно закрывать(который Main)?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.09.2012, 16:43
Ответы с готовыми решениями:

Клиент-серверное приложение: как написать реакцию сервера на каждое сообщение от клиента
В общем пытаюсь разобраться с сетью в C#, условная задача написать сервер - который осуществляет обмен, и клиент - 2 запущенных клиента...

Автоматический поис сервера по заданному порту (Клиент-серверное приложение)
Как на стороне клиента сделать следующее: нужно чтобы при запуске клиента, он автоматически искал сервак, то есть изначально вбит только...

Клиент-серверное приложение: как определить, что сервер/клиент не отвечает в течении определенного времени
Пишу клиент-серверное приложение. Использую TCPListener и TCPClient. Вопрос: как определить что сервер(клиент) не отвечает в течении...

6
 Аватар для Spectral-Owl
608 / 583 / 157
Регистрация: 29.06.2010
Сообщений: 1,620
05.09.2012, 17:00
про текст-бокс скажу, к контролам при многопоточности обращаюсь исключительно так:
C#
1
BeginInvoke(new MethodInvoker(()=>texBox.Text=newRecivedText));
а код на закрытие клиента у меня уморительный:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        public void Stop(Exception e)
        {
            //оповещение о закрытии
            if (OnStop != null) OnStop(this, e);//событие
 
            //сброс флагов
            WantRead = false;
            isConnected = false;
 
            //остановка всего подряд
            try { TimerLister.Stop();       }catch{}//таймер
            try { Sock.Disconnect(false);}catch{}//сокет
            try { Sock.Close();              }catch{}//сокет
            try { ReadThread.Abort();     }catch{}//поток
        }
1
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163
05.09.2012, 17:08  [ТС]
Спасибо за текст бокс)).а вот по изящнее как сделать?я просто в потоках не силён=(.знаю лишь основы потоков. Я как понимаю Abort() останавливает поток(грубо говоря делает "паузу")?
Нельзя ли проще у себя сделать client.Close(), а после поток сам закроется? или я не прав? (где TcpClient client)
P.S.: Почему На ТекстБокс ругнулся, а на table.Rows[0].Cells[1].Value = BitConverter.ToSingle(buf12, i - 40); нет?
0
 Аватар для Spectral-Owl
608 / 583 / 157
Регистрация: 29.06.2010
Сообщений: 1,620
05.09.2012, 17:32
а черт его знает, может таблица создавалась в том же потоке, где изменяется её значение, а текст-бокс по другому?
а по поводу потоков и клиентов: у тебя в потоке нетворкСтрим постоянно читает байты, в то время как определяется видом "client.GetStream();". при закрытии клиента без завершения потока я думаю у тебя нетворкСтрим выдаст ошибку о отключенности клиента. в обработчике этой ошибки стоит закрытие клиента, что собственно вызывет ещё одну ошибку, т.к. клиент и так закрыт(а может и не вызывет, я с сокетами работал постоянно)). после или выдачи, или обработки данной ошибке нетворкстрим заново попытается считать с клиента сообщение, заново выдаст ошибку и т.д.

мой совет: сделать цикл не вечным, в условие поставить булевскую переменную, означающую подключенность клиента. при отключении выставлять её в false. поток всёже желательно завершить, при чем по моему не особо важно каким методом, Abort или Join. поэкспериментируй и с тем и с тем, какой будет работать лучше - тот и оставь)


Abort:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
// Сводка:
        //     Вызывает исключение System.Threading.ThreadAbortException в вызвавшем его
        //     потоке для того, чтобы начать процесс завершения потока. Вызов данного метода
        //     обычно завершает поток.
        //
        // Исключения:
        //   System.Security.SecurityException:
        //     Вызывающий код не имеет необходимого разрешения.
        //
        //   System.Threading.ThreadStateException:
        //     Поток, находящийся в состоянии завершения, приостановлен.


Join:
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
//
        // Сводка:
        //     Блокирует вызывающий поток до завершения потока, продолжая отправлять стандартные
        //     сообщения COM и SendMessage.
        //
        // Исключения:
        //   System.Threading.ThreadStateException:
        //     Вызывающий поток произвел попытку присоединить поток, находящийся в состоянии
        //     System.Threading.ThreadState.Unstarted.
        //
        //   System.Threading.ThreadInterruptedException:
        //     Во время ожидания работа потока была прервана.
0
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163
05.09.2012, 17:41  [ТС]
1.Спасибо за подробный ответ. Т.е. я делаю что то вроде
while(client.Connected) ?
2.Т.е. При нажатие на Дисконнект(я пишу client.Close() после _thread.Abort() и всё?)
3.Да вы правы у меня НетворкСтрим вываливал кучу МессаджБоксов-_-.
4.Мне надает покоя что данные идут в 1сек - 1000структур.
как мне правильно сделать?подать серверу что пора закрыватся и _thread.Abort() или делать client.Close();_tread.Abort()?
5.С текстБоксом стало понятно..а если мне надо ещё выводить 3 графика от переменных которые я получаю..делать 3 BeginInvoke?
0
 Аватар для Spectral-Owl
608 / 583 / 157
Регистрация: 29.06.2010
Сообщений: 1,620
05.09.2012, 18:03
1. да
2. если у клиента нет метода .Disconect(..); то почти. потом кое-какие вызовы методов придётся заключить в try-catch, так как иногда срабатывает двойное отключение, а попытка отключить то что уже отключено часто заканчивается Exception-ом.
5.при обращении к контролам из любого потока кроме базового (а в данном случае получение данных как раз в другом потоке) надо BeginInvoke или эквивалент оному) правда он позволяет записывать и не по одной операции

C#
1
2
3
4
5
6
BeginInvoke(new MethodInvoker(()=>
{
texBox.Text=newRecivedText;
..
..
}));
хотя мог с сигнатурой напутать)
1
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163
06.09.2012, 13:11  [ТС]
2.Насколько я помню то в TcpClien нет метода Disconnet есть Close.Но смысл этого не меняет)
Пишут на форумах что Abort или Join это тоже самое что плевать Омоновцу в лицо , в надежде что ничего не будет. Пишут что в Thread _thread = new Thread(new ThreadStart(СтартПроцесс)); В методе SConnect должна быть какая то переменная отвечающая за "конец" (Логичнее указать некую булеву переменную Б1, потом в Вашей функции СтартПроцесс выполнять процесс до тех пор пока Б1 = труе)
Но у меня Данные могут идти бесконечно=(.Не могу понять как правильно закрыть поток=(

Т.е. Сначала надо закрыть соединение.Потом присвоить переменной что соединение закрыто.Потом как то поток сам закроется?Беда читаю про потоки в rsdn но что то понять не могу как мне тут поступить

Добавлено через 14 часов 18 минут
1.когда я делаю чз BeginInvoke значение "идут" в текст боксе, чз пару секунд они все обнуляются далее снова появляются значения и снова обнуляются.
Как это исправить?

2.делал тоже самое но чз Invoke..значения идут..но при дисконнекте поток уходит в WaitSleepJoin а статус его True;
Если пункт 1. не удачно выбран в моём случае тогда как этот пункт исправить?

Добавлено через 3 минуты
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
        private void ThreadTextBox()
        {
            textBoxThread.Clear();
            textBoxThread.AppendText("Поток(и):" + Environment.NewLine +
                "Имя: " + _t.Name + Environment.NewLine +
                "Статус: " + _t.IsAlive.ToString() + Environment.NewLine +
                "Состояние: " + _t.ThreadState.ToString());
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                if (!flag)
                {
                    button1.Text = "Disconnect";
                    flag = true;
                    _t = new Thread(new ThreadStart(Connect));
                    _t.IsBackground = false;
                    _t.Name = "Thread 1";
                    //_t.SetApartmentState(ApartmentState.STA);
                    _t.Start();
                    ThreadTextBox();
                }
                else
                {
                    button1.Text = "Connect";
                    flag = false;
                    _t.Join(500);
                    ThreadTextBox();
                }
            }
            catch (Exception E)
            {
                MessageBox.Show(E.Message);
            }
        }
 
        private void Connect()
        {
            String server = "192.168.10.100";
            Int32 port = 6000;
            byte[] buf12 = new byte[8048];
            TcpClient client = null;
            NetworkStream networkStream = null;
            client = new TcpClient(server, port);
            networkStream = client.GetStream();
            
            while (flag)
            {
                try
                {
                    button1.Enabled = true;
                    buf12 = new byte[8048];
                    int read = networkStream.Read(buf12, 0, buf12.Length);
                    for (int i = 40; i <= read; i = i + 40)
                    {
                        Invoke(new MethodInvoker(() => textBox1.Text = ("\n" + BitConverter.ToInt16(buf12, i - 8).ToString() + "\n")));
                        table.Rows[0].Cells[1].Value = BitConverter.ToSingle(buf12, i - 40);
                        table.Rows[1].Cells[1].Value = BitConverter.ToSingle(buf12, i - 36);
                        table.Rows[2].Cells[1].Value = BitConverter.ToSingle(buf12, i - 32);
                        table.Rows[3].Cells[1].Value = BitConverter.ToSingle(buf12, i - 28);
                        table.Rows[4].Cells[1].Value = BitConverter.ToSingle(buf12, i - 24);
                        table.Rows[5].Cells[1].Value = BitConverter.ToSingle(buf12, i - 20);
                        table.Rows[6].Cells[1].Value = BitConverter.ToInt16(buf12, i - 16);
                        table.Rows[7].Cells[1].Value = BitConverter.ToSingle(buf12, i - 12);
                        table.Rows[8].Cells[1].Value = BitConverter.ToInt16(buf12, i - 8);
                        table.Rows[9].Cells[1].Value = BitConverter.ToInt16(buf12, i - 6);
                        table.Rows[10].Cells[1].Value = BitConverter.ToInt16(buf12, i - 4);
                      
                    }
                }
                // ошибка соединения
                catch (Exception e)
                {
                    MessageBox.Show(e.Message);
                    //Подстраховка отрубать всё. No Good
                    networkStream.Flush();
                    networkStream.Close();
                    client.Close();
                    _t.Interrupt();
                    _t.Abort();
                    _t.Join(500);
                }
            }
            // end connection
            if (!flag)
            {
                networkStream.Flush();
                networkStream.Close();
                client.Close();
                _t.Interrupt();
                _t.Abort();
                _t.Join(500);
                return;
            }
        }
Добавлено через 4 часа 39 минут
Проблема в том что с TextBox'ом работает Invoke
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.textBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.textBox1.Text = text;
            }
        }
а с Chart'ом некорректно.Т.е. Данные идут в Чарт, чз некоторое время данные начинают приходить "левые"..думаю из за того что данные быстро поступают и поток не успевает записывать всё это дело БитКонвертировать + вызвать инвок на ТекстБокс и Чарт одновременно..данные которые приходят по сети, то ли теряются то ли приходят не те=(..разобраться ну никак не могу.
Помогите вызвать 3 разных Chart'a из другого потока
Invoke,BeginInvoke не помогают..думаю уже делать
C#
1
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;
Дело в том что данные которые приходят чз TCP нужны как и TextBox'у так и 3-м Chart'ам и нескольким TextBox'ом.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.09.2012, 13:11
Помогаю со студенческими работами здесь

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

Как написать клиент-серверное приложение
Привет всем, хочу написать сервер.Пересмотрел кучу уроков и статей и т.д. ,но там нет подробного описания каждого класса и метода. Т.е. они...

Как организовать клиент-серверное приложение
Делаю лабораторную: необходимо написать три приложения на с#, два сервера (ServerInput и ServerProcess) и клиент-приложение (ClientOutput)....

Как создать простенькое клиент-серверное приложение
вобщем такая задача: создать простенькое клиентское и серверное приложение, чтобы с клиента можно было авторизовываться на сервере, и тд и...

Как написать клиент-серверное приложение для управления COM портом
Здравствуйте, Написал в Visual Studio 2010 программу для работы с COM портом - отправка команд(байтов) на микроконтроллер подключенный к...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru