Заполнение памяти используемое программой.
- Войдите на сайт для отправки комментариев
Пнд, 02/09/2013 - 13:34
import processing.net.*;
//Связь с Ethernet клиентом и сервером
int html_port = 80;
int arduino_port = 82;
String IP_arduino = "10.168.2.129";
Server server;
Client client;
int connect_arduino=0;
int connect_server=0;
String list;
//Символ до которого будем считывать данные
byte flag=62;
//Переменные с данными
float [] fl_data=new float [8];
String str_data[];
//Вывод данных в график
float xn=420, xk=420, yn1, yk1, yn2, yk2, yn3, yk3, yn4, yk4;
//Интервал графика 4 мин 1 pix.
long previous_Grafik = 0;
long interval_Grafik = 1000;
boolean grafik = true;
String climate;
void setup()
{
size(800, 600);
background (208, 208, 208);
for (int i=1; i<8; i++) {
fl_data[i]=0.0;
}
}
void draw()
{
//Прием данных с ардуино
client = new Client(this, IP_arduino, arduino_port);
delay (1000);
client.write ("GET/Processing 2.0 ");
delay (1000);
while (client.available()>0){
if (client !=null) {
connect_arduino = 1;
list = client.readStringUntil(flag);
if (list != null) {
str_data = split(list, ';');
}
} else {connect_arduino = 0;}
client.stop ();
//Преобразование string в float
for (int i=1; i<8; i++){
if (str_data[i] != null) {fl_data[i]=float(str_data[i]);}
}
}
if(millis() - previous_Grafik > interval_Grafik) {
previous_Grafik = millis();
print (previous_Grafik);
yn1=545-15*(fl_data[1]-15);
yn2=545-2.25*(fl_data[2]);
yn3=545-15*(fl_data[3]-15);
yn4=545-15*(fl_data[4]-15);
if (grafik == true) {
yk1=yn1;
yk2=yn2;
yk3=yn3;
yk4=yn4;
grafik = false;
}
noStroke ();
stroke(208,208,208);
line (xk+1, 320, xk+1, 545);
line (xk+3, 320, xk+3, 545);
line (781, 320, 781, 545);
stroke(0);
line (xk+2, 320, xk+2, 545);
stroke(255, 0, 0);
line (xn, yn1, xk, yk1);
stroke(0, 125, 255);
line (xn, yn2, xk, yk2);
stroke(128, 0, 0);
line (xn, yn3, xk, yk3);
stroke(128, 0, 128);
line (xn, yn4, xk, yk4);
yk1=yn1;
yk2=yn2;
yk3=yn3;
yk4=yn4;
xk=xn;
xn++;
if (xn > 780) {xn = 420; xk = 420;}
}
}
Получаем данные с Ethernet, переводим в float, рисуем график. Вроде все элементарно и просто. Все работает. Но через сутки непрерывной работы память используеммая программой увеличивается в разы, и вылетает ошибка OutMemoryError. Выкладываю скетч в оригинале, практически пустой, ни чем не перегруженный. Прошу помоч найти проблеммное место, от которого программа в буфере распухает.
Немного отредактировал
import processing.net.*; //Связь с Ethernet клиентом и сервером int html_port = 80; int arduino_port = 82; String IP_arduino = "10.168.2.129"; Server server; Client client; int connect_arduino=0; int connect_server=0; //Символ до которого будем считывать данные byte flag=62; //Переменные с данными float [] fl_data=new float [8]; String [] str_data=new String [8]; //Вывод данных в график float xn=420, xk=420, yn1, yk1, yn2, yk2, yn3, yk3, yn4, yk4; //Интервал графика 4 мин 1 pix. long previous_Grafik = 0; long interval_Grafik = 1000; boolean grafik = true; String climate; void setup() { size(800, 600); background (208, 208, 208); for (int i=1; i<8; i++) { fl_data[i]=0.0; } } void draw() { //Прием данных с ардуино client = new Client(this, IP_arduino, arduino_port); delay (1000); client.write ("GET/Processing 2.0 "); delay (1000); while (client.available()>0){ if (client !=null) { connect_arduino = 1; String list = client.readStringUntil(flag); if (list != null) { str_data = split(list, ';'); } } else {connect_arduino = 0;} client.stop (); //Преобразование string в float for (int i=1; i<8; i++){ if (str_data[i] != null) {fl_data[i]=float(str_data[i]);} } } if(millis() - previous_Grafik > interval_Grafik) { previous_Grafik = millis(); yn1=545-15*(fl_data[1]-15); yn2=545-2.25*(fl_data[2]); yn3=545-15*(fl_data[3]-15); yn4=545-15*(fl_data[4]-15); if (grafik == true) { yk1=yn1; yk2=yn2; yk3=yn3; yk4=yn4; grafik = false; } stroke(208,208,208); line (xk+1, 320, xk+1, 545); line (xk+3, 320, xk+3, 545); line (781, 320, 781, 545); stroke(0); line (xk+2, 320, xk+2, 545); stroke(255, 0, 0); line (xn, yn1, xk, yk1); stroke(0, 125, 255); line (xn, yn2, xk, yk2); stroke(128, 0, 0); line (xn, yn3, xk, yk3); stroke(128, 0, 128); line (xn, yn4, xk, yk4); yk1=yn1; yk2=yn2; yk3=yn3; yk4=yn4; xk=xn; xn++; if (xn > 780) {xn = 420; xk = 420;} } for (int i=1; i<8; i++){ str_data[i] = null; } }Но проблемма осталась. Память растет.
Client каждый раз создается заново. Либо его надо освобождать, либо создать один раз и использовать. Процессинг не пользую, но, сходу только это. Предполагаю, что метод draw вызывается многократно
Можете попробовать поискать как в процессинге принудительно вызывать Garbage Collector (раз там джава под капотом - должен быть сборщик). И попробовать его дергать время от времени.
Можете попробовать поискать как в процессинге принудительно вызывать Garbage Collector (раз там джава под капотом - должен быть сборщик). И попробовать его дергать время от времени.
Если Вы понимаете разницу между "освободить" память и "остановить" клиента, тогда продолжайте дальше, а если не совсем, тогда посмотрите пример, правда Процессинг 2.0+
import processing.net.*; Client myClient; int dataIn; void setup() { size(200, 200); // Connect to the local machine at port 5204. // This example will not run if you haven't // previously started a server on this port. myClient = new Client(this, "127.0.0.1", 5204); } void draw() { if (myClient.available() > 0) { dataIn = myClient.read(); } background(dataIn); }Думаю разницу видно и без объяснений.
Если Вы понимаете разницу между "освободить" память и "остановить" клиента, тогда продолжайте дальше, а если не совсем, тогда посмотрите пример, правда Процессинг 2.0+
import processing.net.*; Client myClient; int dataIn; void setup() { size(200, 200); // Connect to the local machine at port 5204. // This example will not run if you haven't // previously started a server on this port. myClient = new Client(this, "127.0.0.1", 5204); } void draw() { if (myClient.available() > 0) { dataIn = myClient.read(); } background(dataIn); }Думаю разницу видно и без объяснений.
В таком случае читаем комментарии в примере и видим, что там написано примерно следующее:
// Подключение к локальной машине к порту 5204
// Этот пример не будет работать, если сервер в этот момент не слушает порт 5204.
Далее читаем описание к примеру:
Что означает примерно следующее:
Описание: Слиент пытается подключиться к серверу ... Если соединение не установлено, например, хост не найден или сервер не слушает порт, возникает exception.
Т.е. Вы хотите сказать, что запуская пример с параметрами (10 строка):
myClient = new Client( this, ""10.168.2.129"", 82 );
у Вас всё равно возникает exception? При этом Ардуино включен и слушает 82 порт? Пинги идут?
Если идут пинги и всё равно возникает exception, тогда я пас, это уже слишком глубоко для меня.
Мемори лики - это самая "вкуснятина" для мазохистов. Тем более в .net/java которые создавались как-бы для того что-бы они стали невозможны в принципе :(
Попробуйте, для начала, выяснить кто у вас "безобразит". Код работы с сетью или код отрисовки. Попробуйте их поочередно закоментить и покрутить в цикле. Выяснить какая половина "течет".
А в отрисовке, кстати тоже оно бывает. Если верить гуглу. И происходить это может - совсем не по вашей вине.
К примеру:
java - Processing 2.0b8 / Disposing PGraphics objects and memory management - Stack Overflow
Попробуйте еще перед client.stop, следать что-то типа
Вдруг вам сервер закончил свой ответ не символом "перевод строки". Тогда возможно ваш клиент не доконца вычитал "все что пришло", и не освободил какие-то ресурсы. И где-то остается "буффер" который ждет пока данные примутся целиком.
Еще можно client.clear() сделать (совместно с кодом выше).
И еще. попрбуйте Client тоже объявить как локальную переменную. Убрать ее из начала скетча, и вмето
Делать
Что-бы по окончании функции Draw оно понимало что "больше не используем эту переменную" (раз она локальная).
Ну и GC при этом, в профилактических целях - продожать вызывать :)
не решение, но информация http://wiki.processing.org/w/Troubleshooting#Out_Of_Memory_Errors_.28jav...
a System.gc() тут есть? http://www.processing.org/discourse/beta/num_1202914234.html
В таком случае читаем комментарии в примере и видим, что там написано примерно следующее:
// Подключение к локальной машине к порту 5204
// Этот пример не будет работать, если сервер в этот момент не слушает порт 5204.
Далее читаем описание к примеру:
Что означает примерно следующее:
Описание: Слиент пытается подключиться к серверу ... Если соединение не установлено, например, хост не найден или сервер не слушает порт, возникает exception.
Т.е. Вы хотите сказать, что запуская пример с параметрами (10 строка):
myClient = new Client( this, ""10.168.2.129"", 82 );
у Вас всё равно возникает exception? При этом Ардуино включен и слушает 82 порт? Пинги идут?
Если идут пинги и всё равно возникает exception, тогда я пас, это уже слишком глубоко для меня.
Голый код с Clientom грузит память. Код прилагаю.
import processing.net.*; //Связь с Ethernet клиентом и сервером int arduino_port = 82; String IP_arduino = "10.168.2.129"; //Символ до которого будем считывать данные byte flag=62; //Переменные с данными String [] str_data=new String [8]; void setup() { } void draw() { //Прием данных с ардуино Client client = new Client(this, IP_arduino, arduino_port); delay (1000); client.write ("1"); delay (1000); while (client.available()>0){ if (client !=null) { String list = client.readStringUntil(flag); if (list != null) { str_data = split(list, ';'); list = null; } } else {} client.stop (); client.clear(); } }В таком случае читаем комментарии в примере и видим, что там написано примерно следующее:
// Подключение к локальной машине к порту 5204
// Этот пример не будет работать, если сервер в этот момент не слушает порт 5204.
Далее читаем описание к примеру:
Что означает примерно следующее:
Описание: Слиент пытается подключиться к серверу ... Если соединение не установлено, например, хост не найден или сервер не слушает порт, возникает exception.
Т.е. Вы хотите сказать, что запуская пример с параметрами (10 строка):
myClient = new Client( this, ""10.168.2.129"", 82 );
у Вас всё равно возникает exception? При этом Ардуино включен и слушает 82 порт? Пинги идут?
Если идут пинги и всё равно возникает exception, тогда я пас, это уже слишком глубоко для меня.
Сделал по вышеуказанному примеру.
import processing.net.*; //Связь с Ethernet клиентом и сервером Client client; int arduino_port = 82; String IP_arduino = "10.168.2.129"; //Символ до которого будем считывать данные byte flag=62; //Переменные с данными //String [] str_data=new String [8]; String list; void setup() { client = new Client(this, IP_arduino, arduino_port); delay (1000); } void draw() { client.write ("1"); try { //Прием данных с ардуино while (client.available()>0){ list = client.readStringUntil(flag); // str_data = split(list, ';'); client.clear(); } } catch (Exception e) { list = null; } if (list == null) {println ("Null");} if (list != null) {println (list);} }Что изменилось?Память стоит на месте. Сейчас 17000кБь.
Считывание происходит. Но так же вылетает ошибка, после каждого чтения
Есть еще мысли? Мои увы кончились.
В тему призывается великий мастер MAKSIM, да не падают жухлые листья под ЕГО ноги.
Скорее всего падает на Client.write, попробуйте его в try catch, чтобы определиться.
И еще, если flag сразу не появится в буфере, то readStringUntil вернет null
Скорее всего падает на Client.write, попробуйте его в try catch, чтобы определиться.
дык уже определились. Уже же дали эксепшн. Попытка чтения за концом потока.
Помоему идея "создать один клиент" - не то это направление. Оно же при создании клиента - устанавливает соединение. Послали GET, получили ответ - оборвали соединение. После этого любая попытка что-то прочитать - будет давать этот эксепшн. Что логично - соединения нема, а читать пытаемся.. Метода Client.connect - что-то не видно. Только через конструктор. Значит - каждый раз создавать. И пытатся догадатся почему он не освобождает ресурсы при обрыве коннекшина. Вычитывать все БАЙТЫ пришедшие полностью (а не строки), дергать GC и т.п. Причем байты именно вычитывать, а не "очищать буфер" (что-бы серверная часть могла отослать все что хотела целиком и тоже закрыть коннекшн).
Либо... не обрывать коннешн. Подсоеденились и потихоньку читать до потери пульса, когда байты есть. Но это уже зависит от того что на обратной стороне и как оно будет относится к этому (если с той стороны дуина, то на enc28j60 один одновременный конекшн разрешен, если wiznet - до четерых). Ну и в любом случае "обрыв возможен", так что нужно переподсоединятся.
Что значит "возвращаетт значение void"?
Что значит "возвращаетт значение void"?
Значит "ничего не возвращает". Другими словами это не "функция", а "подпрограмма".
void — Википедия
void — Википедия
Да почему же это смущает? Вы же не пытается что-то получить от функции Client.write(). Просто вызвали - и все.
А сама ошибка у вас на строчку выше.
"Client got end-of-stream."
Вообщем переводим это все как "вы пытаетесь что-то делать с потоком после того как клиент получил символ-конца-потока". Вообщем не нужно пытатся что-то читать/писать в соедининие которое оборванно/закрыто.
А вообще, какой-то он "жутко аскетчиный". Ни тебе проверить состояние соединения, ни event-тов для этого.
Может у вас сервер закрыл соединение, а вы пытаетесь что-то писать в него.
дык уже определились. Уже же дали эксепшн. Попытка чтения за концом потока.
Честно говоря я не вижу подтверждение слов ТС, что "падает после каждого чтения".
Согласно приложенного ТС журнала exception, падение может происходить именно на write, потому я и предложить "обложить" его try catch, чтобы в этом убедиться.
Само чтение уже заключено в try catch, потому ошибки давать не должно. Впрочем могу и ошибаться, Java для меня побочный язык, редко пользую.
Объясню смысл своих догадок:
1. Раньше в первом скрипте ТС он записывал строку GET/Processing... через write на Ардуино (я так это понимаю)
2. Теперь он посылает "1"
Как сервер (Ардуино?) должен реагировать на эти две *разные* строки? Мы не знаем, хотя, может быть скетч сервера на Ардуино и есть, а я просто его не заметил.
А то, к примеру, client.write выведет строку, потом всё, что в try catch нее выполнится, потому что ответа от сервера еще нет, а далее мы проверяем неинициализированную переменную list на null.
ЗЫ На счет соединения, пусть остается как сейчас есть, в примерах я нигде не видел, чтобы Client создавался несколько раз. Для теста это сейчас по барабану и лучше оставить как есть, т.е. создавать один раз в setup.
дык уже определились. Уже же дали эксепшн. Попытка чтения за концом потока.
Честно говоря я не вижу подтверждение слов ТС, что "падает после каждого чтения".
Согласно приложенного ТС журнала exception, падение может происходить именно на write, потому я и предложить "обложить" его try catch, чтобы в этом убедиться.
Само чтение уже заключено в try catch, потому ошибки давать не должно. Впрочем могу и ошибаться, Java для меня побочный язык, редко пользую.
Объясню смысл своих догадок:
1. Раньше в первом скрипте ТС он записывал строку GET/Processing... через write на Ардуино (я так это понимаю)
2. Теперь он посылает "1"
Как сервер (Ардуино?) должен реагировать на эти две *разные* строки? Мы не знаем, хотя, может быть скетч сервера на Ардуино и есть, а я просто его не заметил.
А то, к примеру, client.write выведет строку, потом всё, что в try catch нее выполнится, потому что ответа от сервера еще нет, а далее мы проверяем неинициализированную переменную list на null.
ЗЫ На счет соединения, пусть остается как сейчас есть, в примерах я нигде не видел, чтобы Client создавался несколько раз. Для теста это сейчас по барабану и лучше оставить как есть, т.е. создавать один раз в setup.
Скетч ARDUINO
#include <EtherCard.h> #include "DHT.h" #include <OneWire.h> #include <DallasTemperature.h> #include <EEPROM.h> // DHT 22 #define DHTPIN 4 #define DHTTYPE DHT22 DHT dht(DHTPIN, DHTTYPE); float h, t; char H[5]; char T[5]; //DS18B20 #define ONE_WIRE_BUS 5 #define TEMPERATURE_PRECISION 9 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); float t1, t2; char T1[6]; char T2[6]; //Реле 1шт int Relay=6; //EEPROM Уставки сигналов аварий 1-в.пред.темп, 2-н.пред.темп, 3-в.пред.вл. float sp1, sp2, sp3; int simbol; char U1[3], U2[3], U3[3]; //Ethernet static byte mymac[] = {0x00, 0x04, 0xA3, 0x21, 0xCA, 0x38}; byte Ethernet::buffer[1024]; //временной интервал long previousMillis = 0; long interval = 10000; boolean x=true; //Уставки char* climate; // PROGMEM char good [] PROGMEM = "good"; char bad [] PROGMEM = "bad"; //LED ON/OFF, Ethernet_connect int LED_ON = 9; // int LED_E_C = 3; // int brightness = 66; //яркость светодиода на 1.3v // SETUP void setup () { Serial.begin(9600); dht.begin();//DHT22 sensors.begin(); //DS18B20 //Реле 1 шт. pinMode(Relay, OUTPUT); digitalWrite(Relay, HIGH); //LED ON/OFF, Ethernet_connect pinMode(LED_ON, OUTPUT); pinMode(LED_E_C, OUTPUT); analogWrite(LED_ON, brightness); //EEPROM sp1 = EEPROM.read(1); dtostrf(sp1, 2, 0, U1); Serial.println (sp1); sp2 = EEPROM.read(2); dtostrf(sp2, 2, 0, U2); Serial.println (sp2); sp3 = EEPROM.read(3); dtostrf(sp3, 2, 0, U3); Serial.println (sp3); if (!ether.begin(sizeof Ethernet::buffer, mymac, 10)){ Serial.println( "No");} else{ Serial.println("Ok"); } if (!ether.dhcpSetup()){ Serial.println("No"); } else { Serial.println("Ok"); ether.printIp("IP:\t", ether.myip); ether.printIp("Mask:\t", ether.mymask); ether.printIp("Host:\t", ether.gwip); Serial.println(); ether.hisport = 82; analogWrite(LED_E_C, brightness); } } void loop() { //Смена уставок if(Serial.available()){ simbol=Serial.read (); if (simbol==117) { byte t[3] = {0, 0, 0}; for(byte i = 1; i < 4; i++) { t[i] = Serial.parseInt(); EEPROM.write(i, t[i]); } for(byte i = 1; i < 4; i++) { t[i] = EEPROM.read(i); Serial.print(t[i]); if(i < 1) Serial.print(','); else Serial.println(); } } } //Снятие показаний с датчиков //Установка интервала считывания unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval || x==true) { previousMillis = currentMillis; x=false; //DHT22 h = dht.readHumidity(); dtostrf(h, 4, 1, H); t = dht.readTemperature(); dtostrf(t, 4, 1, T); //DS18B20 sensors.requestTemperatures(); t1 = sensors.getTempCByIndex(0); delay (50); dtostrf(t1, 5, 2, T1); t2 = sensors.getTempCByIndex(1); delay (50); dtostrf(t2, 5, 2, T2); Serial.println(); Serial.print("T= "); Serial.println(T); Serial.print("H= "); Serial.println(H); Serial.print("T1= "); Serial.println(T1); Serial.print("T2= "); Serial.println(T2); } //Аварии if (t < sp2 || t1 <sp2 || t2 <sp2 || h > sp3) { digitalWrite (Relay, HIGH); climate=bad; } else { if (t > sp1 || t1 > sp1 || t2 > sp1 || h > sp3) { digitalWrite (Relay, HIGH); climate=bad; } else { digitalWrite (Relay, LOW); climate=good;} } //Ethernet word len = ether.packetReceive(); word pos = ether.packetLoop(len); if(pos) { // Serial.println("---------------------------------------- NEW PACKET ----------------------------------------"); // Serial.println((char *)Ethernet::buffer + pos); // Serial.println("--------------------------------------------------------------------------------------------"); // Serial.println(); BufferFiller bfill = ether.tcpOffset(); bfill.emit_p(PSTR(";$S;$S;$S;$S;$S;$S;$S;$F;>") , T, H, T1, T2, U1, U2, U3, climate); ether.httpServerReply(bfill.position()); } }client.write "1" или client.write "GET/Processing" не имеет значения. Мне GET/Processing был необходим во время отладки скетча ардуино.
client.write заключал в try catch, ошибка не пропала.
Ну вот. Скорее всего на ether.httpServerReply(bfill.position()); соединение было закрыто. Любая попытка после этого read/write - естественно будет заканчиватся фатально.
Нужно подключатся заново. Вообщем, могу только повторить:
>Помоему идея "создать один клиент" - не то это направление.
>Значит - каждый раз создавать. И пытатся догадатся почему он не освобождает ресурсы при обрыве коннекшина. Вычитывать все БАЙТЫ пришедшие полностью (а не строки), дергать GC и т.п
А еще смущает $F в
bfill.emit_p(PSTR(";$S;$S;$S;$S;$S;$S;$S;$F;>")Уже точно не помню, давно не игрался с enc28j60, но кажись $F означает строку из флеша (или значение типа float, не помню). А у вас climate - это обычный char* . Возможно $S более уместен.
Вообщем-то, это не есть причина текущей проблемы, но потом возмжно нужно будет внимательней сюда присмотрется.
>Голый код с Clientom грузит память. Код прилагаю.
Кстати это тоже "не совсем голый". Голый бы не парсил пришедшие строки.
import processing.net.*; //Связь с Ethernet клиентом и сервером int arduino_port = 82; String IP_arduino = "10.168.2.129"; //Символ до которого будем считывать данные byte flag=62; void setup() { } void draw() { //Прием данных с ардуино Client client = new Client(this, IP_arduino, arduino_port); delay (1000); client.write ("1"); delay (1000); while (client.available()>0){ if (client !=null) { String list = client.readStringUntil(flag); client.stop (); client.clear(); } }Или попробуйте вообще вот такое,будет память жрать?
import processing.net.*; //Связь с Ethernet клиентом и сервером int arduino_port = 82; String IP_arduino = "10.168.2.129"; //Символ до которого будем считывать данные byte flag=62; void setup() { } void draw() { //Прием данных с ардуино Client client = new Client(this, IP_arduino, arduino_port); delay (1000); client.write ("1"); delay (1000); while (client.available()>0)client.read(); // вычитываем все пришло. пофиг что. client.clear(); client.stop (); delay(1000); // ждем перед следующим запросом }Ну вот. Скорее всего на ether.httpServerReply(bfill.position()); соединение было закрыто. Любая попытка после этого read/write - естественно будет заканчиватся фатально.
Нужно подключатся заново. Вообщем, могу только повторить:
>Помоему идея "создать один клиент" - не то это направление.
>Значит - каждый раз создавать. И пытатся догадатся почему он не освобождает ресурсы при обрыве коннекшина. Вычитывать все БАЙТЫ пришедшие полностью (а не строки), дергать GC и т.п
А еще смущает $F в
bfill.emit_p(PSTR(";$S;$S;$S;$S;$S;$S;$S;$F;>")Уже точно не помню, давно не игрался с enc28j60, но кажись $F означает строку из флеша (или значение типа float, не помню). А у вас climate - это обычный char* . Возможно $S более уместен.
Вообщем-то, это не есть причина текущей проблемы, но потом возмжно нужно будет внимательней сюда присмотрется.
$F передает данные символьные char/string, в моем случае либо "good", либо "bad".
Вот Вам скетч сервера на Processing
import processing.net.*; Server server; int server_port = 80; float r; int h; void setup() { server = new Server(this, server_port); delay(3000); size (100, 100); background(255); } void draw() { for (int i = 0; i < 16; i++) { r = random(15, 30); h = round (r);} Client client = server.available(); if (client !=null) { String whatClientSaid = client.readString(); if (whatClientSaid != null) { server.write (";"+h+";>"); background(255); textSize(32); fill (0); text (h, 50, 50); server.disconnect(client);} } }Если кто то желает так же по тестировать клиент, прошу принять участие.
Скетч клиента ниже, я так же продолжаю попытки и наблюдения.
import processing.net.*; //Связь с Ethernet клиентом и сервером Client client; int arduino_port = 80; String IP_arduino = "192.168.1.2";//Пишем сюда свой IP адрес сервера //Символ до которого будем считывать данные byte flag=62; //Переменные с данными //String [] str_data=new String [8]; String list; //Временные интервалы //long EthernetMillis = 0; //long Ethernet_interval = 1; void setup() { } void draw() { // long currentMillis = millis(); // if(currentMillis - EthernetMillis > Ethernet_interval) { // EthernetMillis = currentMillis; client = new Client(this, IP_arduino, arduino_port); delay (1000); client.write ("1"); delay (1000); // } try { //Прием данных с ардуино while (client.available()>0){ list = client.readStringUntil(flag); // str_data = split(list, ';'); client.clear(); } } catch (Exception e) { list = null; } if (list == null) {println ("Null");} if (list != null) {println (list);} }Запустил эти скетчи на процессинг 2.0.2 Win7 x64 всё работает нормально.
Поменял только ip, номер порта на 82. И в клиенте list = null; в setup добавил. А, вру, вместо глобального, сделал Client локальным, как Лешак говорил, это правильно. Если оставить глобальным - выдает exception, но потом работает.
Клиент:
import processing.net.*; int arduino_port = 82; String IP_arduino = "127.0.0.1"; byte flag=62; String list; void setup() { list = null; } void draw() { Client client = new Client(this, IP_arduino, arduino_port); delay (1000); client.write ("1"); delay (1000); try { while (client.available ()>0) { list = client.readStringUntil(flag); client.clear(); } } catch (Exception e) { list = null; } client.stop(); if (list == null) { println ("Null"); } if (list != null) { println (list); } }Сервер:
import processing.net.*; Server server; int server_port = 82; float r; int h; void setup() { server = new Server(this, server_port); delay(3000); size (100, 100); background(255); } void draw() { for (int i = 0; i < 16; i++) { r = random(15, 30); h = round (r);} Client client = server.available(); if (client !=null) { String whatClientSaid = client.readString(); if (whatClientSaid != null) { server.write (";"+h+";>"); background(255); textSize(32); fill (0); text (h, 50, 50); server.disconnect(client);} } }Дальше без меня. Лично я бы заюзал clientEvent & serverEvent и не стал бы на серваке закрывать соединение, как то это по гадски, к тебе пришел гость, ты с ним поговорил, и с какими то словами выдворил его за дверь, а может он еще хотел поговорить. Думаю, что соединение в нормальном обмене должен рвать клиент.
Запустил эти скетчи на процессинг 2.0.2 Win7 x64 всё работает нормально.
Поменял только ip, номер порта на 82. И в клиенте list = null; в setup добавил. А, вру, вместо глобального, сделал Client локальным, как Лешак говорил, это правильно. Если оставить глобальным - выдает exception, но потом работает.
Клиент:
import processing.net.*; int arduino_port = 82; String IP_arduino = "127.0.0.1"; byte flag=62; String list; void setup() { list = null; } void draw() { Client client = new Client(this, IP_arduino, arduino_port); delay (1000); client.write ("1"); delay (1000); try { while (client.available ()>0) { list = client.readStringUntil(flag); client.clear(); } } catch (Exception e) { list = null; } client.stop(); if (list == null) { println ("Null"); } if (list != null) { println (list); } }Сервер:
import processing.net.*; Server server; int server_port = 82; float r; int h; void setup() { server = new Server(this, server_port); delay(3000); size (100, 100); background(255); } void draw() { for (int i = 0; i < 16; i++) { r = random(15, 30); h = round (r);} Client client = server.available(); if (client !=null) { String whatClientSaid = client.readString(); if (whatClientSaid != null) { server.write (";"+h+";>"); background(255); textSize(32); fill (0); text (h, 50, 50); server.disconnect(client);} } }Дальше без меня. Лично я бы заюзал clientEvent & serverEvent и не стал бы на серваке закрывать соединение, как то это по гадски, к тебе пришел гость, ты с ним поговорил, и с какими то словами выдворил его за дверь, а может он еще хотел поговорить. Думаю, что соединение в нормальном обмене должен рвать клиент.
что значит "Работает нормально"? Главная проблема решена? Память не копится?
Ну так запустите и проверяйте. Либо опишите Ваш метод проверки памяти.
Работает, это значит, что на сервере отображаются случайные числа в квадратике.
Ваша схема КЛИЕНТА, так же как и моя копит память. Пол часа работы, с 22000КБ до 42000КБ. Вопрос остался открытым. Проблема накопления памяти не решена.
Буду искать.
Это не моя схема, а Ваша, моя схема - создавать клиента в setup и не рубить соединение на сервере, я уже объяснил почему.
Но Ваша схема, при работе с сервером, выдает ошибку
Которую обойти не получается.
Схема - подразумевает что ей следуют и сервер и клиент. Когда кто-то один из них работает по одной "схеме", а кто-то "по другой" - получается фигня.
Я уже вроде детально расписывал "почему у вас не получается" (№26).
И вы выборочно очень читаете ответы. "не рубить соединение на сервере" - было проигнорировано.
А уж сколько раз было проигнорировано "попробуйте вычитывать ВСЕ байты" (даже код дал для этого #28), "попробуйте вызвать Garbage Collector" - я уже со счета сбился.
Схема - подразумевает что ей следуют и сервер и клиент. Когда кто-то один из них работает по одной "схеме", а кто-то "по другой" - получается фигня.
Как на enc28j60 осуществить не обрыв связи с клиентом? К сожалению в примерах и статьях такой информации не видел.
Я уже вроде детально расписывал "почему у вас не получается" (№26).
Да, я это читал и согласен, но не представляю как зделать иначе.
А уж сколько раз было проигнорировано "попробуйте вычитывать ВСЕ байты" (даже код дал для этого #28), "попробуйте вызвать Garbage Collector" - я уже со счета сбился.
Пробовал, попробую еще раз, вместе с вычитыванием всего что прислал сервер. Результаты напишу.
import processing.net.*; //Связь с Ethernet клиентом и сервером int arduino_port = 80; String IP_arduino = "88.85.206.140"; //Символ до которого будем считывать данные byte flag=62; void setup() { } void draw() { //Прием данных с ардуино Client client; client = null; client = new Client(this, IP_arduino, arduino_port); delay (1000); client.write ("1"); delay (1000); while (client.available()>0)client.read(); // вычитываем все пришло. пофиг что. client.clear(); client.stop (); System.gc(); println (client); println (client.read()); delay(1000); // ждем перед следующим запросом }Вот код, память грузит.
21 строку перенесите в 40-ю, по крайней мере система будет знать, что эта память Вам больше не нужна
зделал. Она там была, я ее в 21 перенес, чтобы уж наверняка перед созданием нового клиента обнулялась.
зделал. Она там была, я ее в 21 перенес, чтобы уж наверняка перед созданием нового клиента обнулялась.
Это неправильно, потому что локальный объект создается, Вы его обнуляете (бессмысленно, поскольку он только что появился), затем создаете. А то, что я написал означает, что "я работу с объектом закончил, можно выносить".
UPD: А после того, как мы сообщили, что "можно выносить", сборщик мусор в своё время эту память освободит. А уж через сколько это произойдет - я не подскажу, моих знаний недостаточно.
зделал. Она там была, я ее в 21 перенес, чтобы уж наверняка перед созданием нового клиента обнулялась.
Это неправильно, потому что локальный объект создается, Вы его обнуляете (бессмысленно, поскольку он только что появился), затем создаете. А то, что я написал означает, что "я работу с объектом закончил, можно выносить".
UPD: А после того, как мы сообщили, что "можно выносить", сборщик мусор в своё время эту память освободит. А уж через сколько это произойдет - я не подскажу, моих знаний недостаточно.
тогда System.gc(); имеет смысл поставить после client=null ?
Кстати println (client); выводит следующее значение: processing.net.Client@12922f6, где 12922f6 каждое новое соединение разное значение.
>тогда System.gc(); имеет смысл поставить после client=null ?
да.
Кстати println (client); выводит следующее значение: processing.net.Client@12922f6, где 12922f6 каждое новое соединение разное значение.
У меня для вас плохие новости :(
Не вы один на это наткнулись :(
Newbie with Out of memory when using client.write() - Processing Forum - так решение и не нашли.
Так же эта проблема находится висит на баг-трекере
Issue 1362 - processing - Recreating Client instance will cause an out-of-memory error - An open source programming language and environment for creating images, animation, and interactions - Google Project Hosting
И как видим - он не отмечена как "решенная". Так что - очень вероятно что это банально "известный баг".
У вас какая версия процессинга, последняя? Если нет - попробуйте на последнюю апгрейднутся, может там пофиксали.
У меня для вас плохие новости :(
Не вы один на это наткнулись :(
Newbie with Out of memory when using client.write() - Processing Forum - так решение и не нашли.
Так же эта проблема находится висит на баг-трекере
Issue 1362 - processing - Recreating Client instance will cause an out-of-memory error - An open source programming language and environment for creating images, animation, and interactions - Google Project Hosting
И как видим - он не отмечена как "решенная". Так что - очень вероятно что это банально "известный баг".
У вас какая версия процессинга, последняя? Если нет - попробуйте на последнюю апгрейднутся, может там пофиксали.
последняя....
Как же мне тогда поступить?
попробуйте, перед client.stop() сделать
this.unregisterMethod("dispose",client);если будет ругатся что "нет такого метода unregisterMethod", то это означает что у вас старый процессинг. Тогда вот так:
В общем, решение пока такое, Памяти хватает на 5 часов стабильной работы. Буду использовать планировщик задач Windows для перезапуска приложения, ну и ждать когда пофиксят баг.