Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
videoLoL
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163
1

Клиент-Сервер: как реализовать

06.09.2012, 14:05. Просмотров 1310. Ответов 10
Метки нет (Все метки)

Во общем есть Сервер на Ansi-C
Задача:нужно написать клиента C#
Данные поступают в 1с-1000структур по 40байт каждая структура.
Нужно выводить в данные в DataGridView в 3 Chart'a в 3 TextBox'a.

Как это реализовать?
Сейчас работает так.
Клиент подсоединяется - метод Connect.
В этом методе чз флаг делается While в нем Try-Catch. В Try-Catch данные записываются в DataGridView с помощью BitConverter'a. Т.к. я Добавил в Конструктор Формы Добавление строк в DataGridView ,то работать можно в другом потоке беспроблем.
Далее на Событие нажатие кнопки создаём Thread от Connect;

Тут начинает возникать проблема вывода в TextBox. Делаю чз Invoke с проверкой на InvokeRequired.
Так вот после этого самого Invoka (пробывал и BeginInvoke) начинается чёрти что..пакеты которые приходят увеличиваются в количестве..т.е. я выводил в DataGridView пакеты приходили по 1480байт(37структур) тут же количество данных больше 70000байт. В DataGridView т.к. там BitConverter данные в таблици сходят с "ума". Когда же подключаю ещё чз Invoke ДВА Chart'a тут происходит ещё хуже..проц кушает 100% виснуть начинает обсалютно всё..
Сделал кнопку дисконнект. которая меняет ГЛОБАЛЬНУЮ Bool переменную которая обрабатывается в методе Connect циклом While.Далее цикл останавливается.и
C#
1
2
3
4
5
6
7
8
9
10
11
            if (!flag)
            {
                networkStream.Flush();
                networkStream.Close();
                client.Close();
                _t.Interrupt();
                _t.Abort();
                _t.Join(500);
                
                return;
            }
Но ничего не помогает..данные идут дальше!!и чз минуту останавливается ..статус Thread (WaitSleepJoin)

Как решить проблему с Выводом в Чарты,Датагриды,текстбоксы?Или я вообще не правильно начал делать проект?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.09.2012, 14:05
Ответы с готовыми решениями:

Клиент-сервер. Как в многопользовательском чате реализовать личные сообщения
Console.WriteLine(Func.ToDateTime() + "Server started."); TcpListener listener =...

Можно ли реализовать сервер и клиент в одном приложении
Вот пишу программу, обмена сообщениями между 2 приложениями. Хочу сделать что бы каждое приложение...

Реализовать взаимодействие клиент-сервер с использованием задач (Task)
Реализовать ситуацию взаимодействия по типу клиент-сервер с использованием задач (Task). Для...

Клиент-сервер: Как определить, что клиент отключился?
Привет. Есть клиент и сервер, при подключении клиента, на сервере создается класс, который содержит...

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

10
KeBJIaP
145 / 142 / 32
Регистрация: 21.01.2012
Сообщений: 545
Завершенные тесты: 1
06.09.2012, 14:51 2
Я бы сделал так:
1) Поток прослушки сокета запускается из основного. Сокет получает сообщение и пишет его в некую очередь отработки.
2) В основном потоке происходит обработка очереди. Не вызываем дополнительных потоков чтобы не надо было инвочить контроллы(все-таки надо быстро работать). Соответственно после обработки очередного сообщения принимаем решение об обновлении контролов.
3) Если понадобится еще какая-то функциональность, запускаем отдельным потоком.
0
videoLoL
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163
06.09.2012, 15:02  [ТС] 3
Если я понял вас..то не использовать Дополнительный Поток..
Я делал в Основном потоке подключение и битконверт.но тогда форма вообще виснет.приходится делать дополнительный поток на подключение и конвертацию данных.да и ещё количество данных может возрасти в 80раз=(.
как возможно сделать быстро и качественно?надо оптимизировать на каждом шагу?да и данные бесконечные=(..т.е. идут пока я сам не отключу соединение
0
KeBJIaP
145 / 142 / 32
Регистрация: 21.01.2012
Сообщений: 545
Завершенные тесты: 1
06.09.2012, 15:05 4
1 поток - основной, в котором создается форма, в нем пусть обрабатываются сообщения.
2 поток (запускается из первого) - сокет, который будет полученные сообщения просто добавлять в очереди.
0
06.09.2012, 15:05
videoLoL
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163
06.09.2012, 15:08  [ТС] 5
что подразумевается под полученные сообщения просто добавлять в очереди?
куда-то их сохранять?
0
KeBJIaP
145 / 142 / 32
Регистрация: 21.01.2012
Сообщений: 545
Завершенные тесты: 1
06.09.2012, 15:09 6
Массив байтов, полученный в буфер сокета
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static Queue<Mess> qu= new Queue<Mess>();
 
public void AddToQueue(byte[] buffer)
{
    qu.Enqueue(new Mess(buffer))
}
 
public class Mess
{
    public byte[] mess;
    public Mess(byte[] buffer)
    {
        this.mess = buffer;
    }
}
В общих чертах
0
videoLoL
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163
06.09.2012, 15:11  [ТС] 7
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
private unsafe void Connect()
        {
            String server = "192.168.10.100";
            Int32 port = 6000;
            byte[] buf12 = new byte[8192];
            TcpClient client = null;
            NetworkStream networkStream = null;
            client = new TcpClient(server, port);
            networkStream = client.GetStream();
            while (flag)
            {
                try
                {
                    
                    buf12 = new byte[8192];
                    int read = networkStream.Read(buf12, 0, buf12.Length);
                    for (int i = 40; i <= read; i = i + 40)
                    {
                        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);
                        SetTextSafe(read == 1480 ? " \t" : " " + read.ToString());
                        
                    }
                }
                // ошибка соединения
                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;
            }
        }
Добавлено через 36 секунд
Буфер сокета?можно будет немного по подробнее
0
KeBJIaP
145 / 142 / 32
Регистрация: 21.01.2012
Сообщений: 545
Завершенные тесты: 1
06.09.2012, 15:19 8
Ну это код клиента, покажи сервер

Добавлено через 1 минуту
А так ты вообще сокеты не используешь. Почитай про сервер на асинхронном сокете.
http://cyber-blog.klan-hub.ru/2010/0...тами-в-c-шарп/
0
videoLoL
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163
06.09.2012, 15:30  [ТС] 9
Сервер на Ansi-C =) сразу извиняюсь за быдлокод
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <bur/plctypes.h>
#include <bur/plc.h>
#include <stdlib.h>
#include <string.h>
#include <astcp.h>
 
#define MAX 32768
#define MIN -32767
#define _Kod 19660
#define _UKod 3276,0
#define _UM 2500
#define _U 6
 
typedef struct 
{
    REAL x;
    REAL w;
    REAL Kp;
    REAL Ki;
    REAL U;
    REAL xPerc;
    INT xCentr;
    REAL wPerc;
    INT K;
    INT P;
    INT I;
}PIDLP;
 
typedef struct
{
    INT n;
    BOOL flag;
    BOOL SignalStart;
}Circle500;
 
_GLOBAL INT AnInput,AnOutput;
_GLOBAL PIDLP _Pid;
_LOCAL Circle500 _C500; 
 
/**/
_GLOBAL BOOL flag_onoff, open_ready;    
_GLOBAL UINT open_port;
_GLOBAL UINT recv_packet;
_GLOBAL PIDLP _send_packet;
_GLOBAL UINT _send;
_LOCAL TcpServer_typ TCPserv;
_LOCAL TcpSend_typ TCPsend;
_LOCAL TcpOpen_typ TCPopen;
_LOCAL TcpClose_typ TCPclose;
_LOCAL TcpRecv_typ TCPrecv;
_LOCAL TcpIoctl_typ TCPioctl;
_LOCAL UDINT numclnt_old;
 
_LOCAL STRING ipadr[16];; 
_LOCAL USINT close_ready;
/**/
 
 
 
_INIT void init(void)
{
    /**/
    open_ready = 1;
    close_ready = 0;
    flag_onoff = 1;
    open_port = 6000;
    strcpy(ipadr, "192.168.10.100");
    numclnt_old=0;
    /**/
 
    _Pid.xCentr = 0;
 
    _C500.n = 0;
    _C500.flag = 0;
    _C500.SignalStart = 0;
}
 
_CYCLIC void cyclic (void)
{
/**/
    _Pid.K++;
    if (flag_onoff == 1) /*Vkl tenzometriu*/
    {
        /*Otkrivaem port*/
        if (open_ready) 
        {
            open_ready = 0;
            TCPopen.enable = 1;             
            TCPopen.pIfAddr = (UDINT) &ipadr;
            TCPopen.port = open_port;             /* Own port number */
            TCPopen.options = tcpOPT_REUSEADDR;             
            TcpOpen(&TCPopen);           
        }
    
        if(TCPopen.status == 65535) 
            TcpOpen(&TCPopen);
        else
        {
            /*close_ready = 1;  */
            TCPserv.enable = 1;
            TCPserv.ident=TCPopen.ident;
            TcpServer(&TCPserv);
        
            /*Posilka*/
            if (TCPserv.identclnt>0)
            {                                 
                TCPsend.enable = 1;                 
                TCPsend.ident = TCPserv.identclnt;     
                TCPsend.pData = (UDINT)&_Pid;                           
                TCPsend.datalen = sizeof(_Pid); 
                TcpSend(&TCPsend);                  
 
                    TcpSend(&TCPsend);                                                                                     
            }
                                
            if(TCPserv.identclnt>0)
            {
                TCPrecv.enable = 1;     
                TCPrecv.ident = TCPserv.identclnt;
                TCPrecv.pData = (UDINT)&recv_packet;    
                TCPrecv.datamax = sizeof(recv_packet);
                TcpRecv(&TCPrecv); 
                if (TCPrecv.status !=0)
                    TcpRecv(&TCPrecv);                                                       
            }                    
        }
    }
 
    /*if flag_onoff=0*/
    else 
    {
        open_ready = 1;
        if (close_ready == 1)
        {
            TCPclose.enable = 1;
            TCPclose.ident=TCPserv.identclnt;
            TcpClose(&TCPclose);
            TCPopen.enable = 0;
            TCPopen.pIfAddr = 0;
            TCPopen.port = 0;
            TCPopen.options = 0;
            TCPserv.enable = 0;
            TCPserv.ident = 0;  
            TCPsend.enable = 0; 
            TCPsend.ident = 0;  
            TCPsend.datalen = 0; 
            open_ready = 0;
            close_ready = 2;
        }
        else if ((TCPclose.status == 65535) && (close_ready == 2)) 
            TcpClose(&TCPclose);
    }
/**/
    /*On\Off Signal*/
    if(_C500.SignalStart)
    {
        if(_C500.flag == 0)
        {
            _C500.n--;
        }   
        else 
            _C500.n++;
    }   
    
    if (_C500.n%500 == 0 && _C500.n!=0)
    {
        _C500.flag = !_C500.flag;       
    }
     
    /*Pid*/ 
    _Pid.U = _U + ((float)AnInput - (float)_Kod)/_UKod; 
    _Pid.x = ((float)AnInput - (float)_Kod)*10000/13107 - _Pid.xCentr; 
    _Pid.xPerc = _Pid.x/100.000;
    _Pid.wPerc = _Pid.w/100.000;
    
    _Pid.P = (int)(((_Pid.wPerc - _Pid.xPerc) * 32768.000/100.000) * _Pid.Kp);
    _Pid.I = _Pid.I + (_Pid.wPerc - _Pid.xPerc) * 32768.000/100.000;
    if (_Pid.P + _Pid.I*_Pid.Ki > 32768)
        AnOutput = MAX;
    else if (_Pid.P + _Pid.I*_Pid.Ki < -32678)
        AnOutput = MIN;
    else 
        AnOutput = _Pid.P + _Pid.I*_Pid.Ki;
    
}
Добавлено через 2 минуты
я побывал чз Сокет..но что то чз TcpClient лучше получилось..хотя я наверно не так красиво всё сделал как надо

Добавлено через 2 минуты
единственное что важно это
C
1
2
3
4
5
6
7
8
9
10
f (TCPserv.identclnt>0)
            {                                 
                TCPsend.enable = 1;                 
                TCPsend.ident = TCPserv.identclnt;     
                TCPsend.pData = (UDINT)&_Pid;                           
                TCPsend.datalen = sizeof(_Pid); 
                TcpSend(&TCPsend);                  
 
                    TcpSend(&TCPsend);                                                                                     
            }
Добавлено через 5 минут
На делфи клиент есть может кто поможет перевести его на С#.Там проблема с потоками =(
0
freeba
Неадекват
1290 / 1086 / 207
Регистрация: 02.04.2010
Сообщений: 2,507
Записей в блоге: 2
Завершенные тесты: 2
06.09.2012, 19:49 10
Цитата Сообщение от videoLoL Посмотреть сообщение
Но ничего не помогает..данные идут дальше!!
Сдается мне батенька - сервер у вас пошаливает.
Цитата Сообщение от videoLoL Посмотреть сообщение
Сервер на Ansi-C =)
Это не ANSI-C, в его стандартной либе нет real - там creal.

Имхо не проще набросать асинхронный сервер на том-же питоне (или эрланге), производительность особая все равно не нужна. А клиент на шарпе на чистых сокетах используя socket.BeginRecieve, чтобы с потоками не заморачиваться и в AsyncCallback-функции уже на форме все заполнять и отрисовывать.
0
videoLoL
7 / 7 / 2
Регистрация: 20.04.2011
Сообщений: 163
07.09.2012, 08:54  [ТС] 11
сервак не могу на брасать ибо B&r микроконтроллер. написанно что Ansi-c.
про клиента попробую завтра на сокетах мб что получится. но помоему будет всё также=(..ибо он всё равно чз tcpclient работает если я не ошибаюсь(или ошибаюсь)
Пытаюсь подключить поток и заодно разобраться с ними-_-.. завтра попробую BackgroundWorker мб что выйдет.
Мне кажется данные идут дальше потому что в цикле который в методе Коннект который запускает Поток находится бул переменная..я её "Фэлсю" а данные с прошлого раза ещё идут и количество пакетов больше становится и количество увеличивается вот это почему я понять не могу=(

Добавлено через 11 часов 14 минут
Сервер делает только отправку сообщений и принятие структур по требованию и то это будет происходить крайне редко. пробывал чз socket.BeginRecieve но тогда вообще всё зависает=(. пробывал чз socket.Recieve но тут происходит для меня не понятное.данные поступают и тут же клиент подвисает.видимо где то буффер переполняется или ещё что то =(..вот понять не могу что именно.может быть использовать мой вариант с подключение Доп.Потока только не Thread, BackgroundWorker?

Добавлено через 1 час 23 минуты
Как я понимаю на форме контроллы "загружаются" в основой поток.
в нём я открываю Доп.Поток. это доп поток считывает данные из сети..и одновременно я хочу ещё и рисовать и писать..Рисовать чз Invoke\BeginInvoke аналогично и писать не успевает, пока он рисуют уже данные поступают..т.е. Скорость(Поступление данных) > Скорости(Отрисовки,Записи)

Как же мне тут вылечить эту проблему?Сервер real-time ему без разницы он может слать данные делительный срок в данном случае недели две.

Тут видимо проблема в том что данные одни, а они нужны нескольким контроллам..как тут мне поступить? синхронно их отдавать.ибо мне важно вывести 3 Графика..
как открывать 3 доп потока? с семафорами, локами? или как то можно их синхронизировать?
0
07.09.2012, 08:54
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.09.2012, 08:54

Как красиво организовать клиент-сервер
Здравствуйте! Пишу приложение: сервер бесконечно ждет подключения нового клиента, при подключении...

Как написать простой клиент-сервер
Доброго времени суток господа. Возникла маленькая проблемка. Пытаюсь разобраться с сокетами, но...

Как написать небольшой клиент-сервер
Всем привет. Мне нужно написать два приложения: Первое пустое, оно выступает в роли сервера, а...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru