博客地址已更改,文章數量較多不便批量修改,若想訪問源文請到 coologic博客 查閱,網址:www.coologic.cn
如本文記錄地址為 techieliang.com/A/B/C/ 請改為 www.coologic.cn/A/B/C/ 即可查閱
版權聲明:若無來源注明, Techie亮博客文章均為原創。 轉載請以鏈接形式標明本文標題和地址:
本文標題:Matlab中TCP通訊-實現外部程序提供優化目標函數解 本文地址: http://techieliang.com/2017/12/551/
1. 介紹
TCP如此常用的通訊功能,matlab自然也是支持的。而在用途方面也有很多,比如matlab優化問題中目標函數可以是其他程序的運算結果,此時需要動態的每次優化調用其他程序,這時可以使用tcp實現兩程序之間的數據交互,由matlab的優化工具箱提供每次優化的設計變量值,有某程序提供基於設計變量得出的運算結果值作為目標函數的解。
2. TCP使用方法
Matlab 對TCP的封裝很好,只有在建立和關閉tcp需要專用的函數,其他操作均與文件操作完全一致。
下面先給出一個用於優化的范例:
主腳本:
- clc;clear;
- %開啟tcp
- global mtcpip %用全局變量方便優化函數中使用tcp
- global circle_number
- circle_number=0;
- mtcpip=tcpip('127.0.0.1', 8000);
- fopen(mtcpip);
- fwrite(mtcpip,['Matlab Connect in',char(13), char(10)])
- %優化算法--
- current_value = [123123 123123 123123 123321 123123 123123 13 123123 123123];
- lb=[];
- ub=[];
- new_error = fmincon(@matlab_function,current_value,[],[],[],[],lb,ub);%優化
- % 優化技術-關閉tcp
- fwrite(mtcpip,['Matlab Disconnect',char(13), char(10)])
- fclose(mtcpip);
- delete(mtcpip);
優化函數:
- function [ f ] = matlab_function( x )
- global mtcpip
- global circle_number
- circle_number=circle_number+1;
- x_size = size(x);
- send_text=['matlabvalue--'];
- for i=1:1:x_size(2)
- if i==x_size(2)
- send_text=[send_text,num2str(x(i),'%.4f'),char(13), char(10)];
- else
- send_text=[send_text,num2str(x(i),'%.4f'),';'];
- end
- end
- fwrite(mtcpip,send_text);
- while 1
- A = fread(mtcpip, 20);
- text = char(A);
- text_size = size(text);
- if text_size(1)<2
- continue;
- end
- if text(1) == 'm' && text(2) == 'r'
- text=text';
- text = strrep(text,'@','');//符號替換
- text = strrep(text,'mr','');
- text = strrep(text,'#','');//刪除末尾多余的占位符,我用#作為占位符了
- f = str2double(text);
- ['circle one begin',num2str(circle_number,'%.4f')]
- break;
- end
- end
- end
此范例的優化函數中利用一個while 1實現了阻塞,會不斷的循環等待其他程序算出結果后成功接收到結果才完成單步優化計算。我設定了結果的固定表示格式
“mrXXXXXX###########@”消息總長度為20,末尾為@作為結束符,mr作為開頭,XXXX為消息實際內容,#為占位符,以此方式保證每次發送消息均為20長度,同時可以通過數據頭的mr確定收到的內容是不是傳給matlab的結果文件(若多個tcp通訊需要做此判斷防止發送錯誤,導致后續結果計算錯誤),只有當結果均計算正確,才目標函數返回值賦值為接收到的結果,並break進入下一次優化迭代
2.1. 創建tcp
tcpip()函數創建一個tcp對象,可以在matlab中用help tcpip查到幫助,上述范例為開啟客戶端。對於目標主機ip可以用’localhost’代替127
注意此函數第三項參數用來配置為服務端還是客戶端,若不寫默認為客戶端
注意開啟完成后的返回值一定要保存,后續開啟、收發和關閉均需要使用,此處因為需要跨多個m文件使用此tcp所以設置為了全局變量
2.2. 開啟tcp
fopen即可,參數傳入tcp對象
2.3. 關閉tcp
fclose? 就可以關閉一個已經開啟的tcp了,參數傳入tcp對象
建議用delete釋放tcp對象的內容
2.4. 收發
啟動tcp以后,matlab支持直接用文件讀寫的方式進行tcp消息收發,直接使用fwrite、fread即可,第一個參數要傳入開啟tcp對象
3. 其他
3.1. matlab發送回車,換行符的方法
matlab不支持在字符串中用\n實現換行,但是可以直接發送對應ASCII碼,可以通過char(13), char(10)實現換行的發送,注意這兩個對應的是\r\n,windows中是用\r\n實現換行,若linux直接發送\n的10即可。
3.2. matlab字符串連接
很簡單[send_text,num2str(x(i),’%.4f’),char(13), char(10)],直接用行向量數組即可,本身matlab就是用char數組表示字符串的
3.3. 接收數據為列向量,轉行向量方法
直接text=text’;即可,和矩陣操作一樣
別用string()去強制字符串,matlab中本身就是用char數組表示字符串,沒有單獨的字符串概念,轉換完也沒區別
3.4. 字符串處理-替換
text = strrep(text,’@’,”);實現了吧text中的所有@刪除,上述范例是因為發送來的數據是固定的格式,對格式做預處理
由於matlab接收tcp消息是按照固定長度,所以發送端若發送的內容不夠長,可以在后面加占位符,matlab接收到以后刪除占位符即可
3.5. 接收長度限制
A = fread(mtcpip, 20);
此函數指定了接收的長度,若消息發送的長度不夠,會一直阻塞,直到超時以后才會接收已有的為滿足長度要求的數據,為了保證立即接收,建議發送數據末尾用占位符,接收到以后再替換掉。