基于PXA270嵌入式系統(tǒng)的Socket通信設(shè)計(jì)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
1 引言
PXA270 是Intel 公司的一款基于XScale 架構(gòu)的高集成度高性能嵌入式處理器,采用ARMv5TE內(nèi)核,包含了Intel的SpeedStep 技術(shù),優(yōu)化了處理器的功耗,可以動態(tài)調(diào)節(jié) CPU 的電壓和頻率來節(jié)省電源的功耗。支持多種嵌入式操作系統(tǒng),如Linux、WinCE、Nucleus、Palm OS、VxWorks等。
Socket接口是TCP/IP網(wǎng)絡(luò)層的API,定義了許多函數(shù)和例程,可以用它們來開發(fā)TCP/IP網(wǎng)絡(luò)層的應(yīng)用程序。網(wǎng)絡(luò)的Socket數(shù)據(jù)傳輸是一種特殊的I/O,具有一個(gè)類似于打開文件的函數(shù)調(diào)用Socket(),該函數(shù)返回一個(gè)整型的Socket描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^該Socket實(shí)現(xiàn)的。
2 系統(tǒng)設(shè)計(jì)
系統(tǒng)的設(shè)計(jì)分為服務(wù)器端和客戶端設(shè)計(jì)兩部分,服務(wù)器端為運(yùn)行Linux操作系統(tǒng)的PC機(jī),客戶端為PXA270系統(tǒng),在該系統(tǒng)中移植和構(gòu)建Linux嵌入式操作系統(tǒng),兩者通過Switch交換機(jī)進(jìn)行網(wǎng)絡(luò)通信。
2.1 系統(tǒng)工作原理
在Linux 操作系統(tǒng)中,Socket 屬于文件系統(tǒng)的一部分,網(wǎng)絡(luò)通信可以被看作是對文件的讀取。Linux 擁有POSIX 標(biāo)準(zhǔn)庫函數(shù),Socket()、Bind()、Sendto()、Recvfrom()等庫函數(shù)可以方便地實(shí)現(xiàn)客戶/ 服務(wù)器模型中數(shù)據(jù)的傳送與接收。系統(tǒng)設(shè)計(jì)主要的目的是完成服務(wù)器和客戶端網(wǎng)絡(luò)通信的實(shí)現(xiàn)。首先啟動宿主機(jī)和客戶機(jī)的操作系統(tǒng)Linux,然后每個(gè)模塊加載網(wǎng)絡(luò)設(shè)備驅(qū)動程序,最后通過TCP/IP協(xié)議建立雙方的通信鏈路,完成Socket通信,詳細(xì)情況如圖1所示。
2.2 嵌入式TCP/IP協(xié)議架構(gòu)
嵌入式系統(tǒng)作為TCP服務(wù)器,在三次握手建立連接的過程中,嵌入式系統(tǒng)作為監(jiān)聽狀態(tài)的服務(wù)器,處于LISTEN狀態(tài),等待對方發(fā)起連接。當(dāng)它接收到SYN數(shù)據(jù)片,立即發(fā)出SYN+ACK的數(shù)據(jù)片確認(rèn)收到對方的SYN,此時(shí)變?yōu)镾YN_ RECEIVED狀態(tài)。再接收到對方返回的一個(gè)包含ACK的空數(shù)據(jù)片則三次握手完成,進(jìn)入ESTABLISHED狀態(tài),最后進(jìn)行TCP數(shù)據(jù)通訊。
圖1 系統(tǒng)的原理示意圖
嵌入式系統(tǒng)建立連接時(shí)初始化序列號,然后根據(jù)對方發(fā)包中的值來確定序列號,不記憶序列號,不能識別重復(fù)報(bào)文。嵌入式服務(wù)器僅僅在服務(wù)器端響應(yīng)客戶端的請求,接收一個(gè)發(fā)送一個(gè)確認(rèn)回答,不考慮失序問題。同時(shí)接收到TCP請求后,將存儲于發(fā)送緩沖區(qū)中的數(shù)據(jù)立即發(fā)送即可,只需一個(gè)數(shù)據(jù)包就能完成,也不需考慮失序問題。
因?yàn)榍度胧较到y(tǒng)采用滑動窗口為1的傳輸方式,即發(fā)送一次數(shù)據(jù)包就等待返回應(yīng)答,因此當(dāng)接收不到確認(rèn)包,就認(rèn)為自己發(fā)送的包丟失,直接發(fā)送上次發(fā)送的數(shù)據(jù)。TCP的連接中,當(dāng)客戶機(jī)異常導(dǎo)致連接崩潰時(shí),嵌入式系統(tǒng)發(fā)數(shù)據(jù)時(shí)會被回復(fù)復(fù)位信號,回到初始狀態(tài)。嵌入式TCP/IP協(xié)議如圖2所示。
3 客戶端/服務(wù)器端功能設(shè)計(jì)
在TCP/IP網(wǎng)絡(luò)中,通信的兩個(gè)進(jìn)程間相互作用的主要模式是客戶/服務(wù)器模式,即客戶端向服務(wù)器端發(fā)出服務(wù)請求,服務(wù)器接收到請求后,提供相應(yīng)的服務(wù)??蛻?服務(wù)器模式在操作過程中采取的是主動請求方式。
圖2 嵌入式TCP/IP圖解[!--empirenews.page--]
3.1 客戶端程序設(shè)計(jì)
客戶端可以向服務(wù)器端發(fā)送連接請求,并且客戶端也可以接收到來自服務(wù)器端發(fā)送回來的數(shù)據(jù)??蛻舳丝梢耘袛喈?dāng)前自己的工作狀態(tài),如連接的建立,啟動的成功和數(shù)據(jù)包通信的個(gè)數(shù)等??蛻舳顺绦蛟O(shè)計(jì)主要按以下的步驟完成函數(shù)的調(diào)用:
①建立自己的Socket(并驗(yàn)證建立成功);
②啟動連接(并驗(yàn)證建立成功);
③返回連接信息;
④接收收到的數(shù)據(jù);
⑤判斷數(shù)據(jù)的屬性。
客戶端程序設(shè)計(jì)的程序基本流程如圖3所示。
圖3 客戶端程序簡單示意圖
客戶端打開通信通道,并連接到服務(wù)器所在主機(jī)的特定端口,向服務(wù)器發(fā)送請求報(bào)文,等待并接收應(yīng)答,請求結(jié)束后關(guān)閉通信通道并終止通信??蛻舳酥饕绦蛉缦拢?br /> Int main(int argc,char *argv[])
if(argc!=3)
printf("error!!!please enter the remote IP and PORT please!!! the form like 192.168.0.* 4000\n");
mysocket=socket(AF_INET,SOCK_STREAM,0); //建立一個(gè)套接字
if(mysocket==-1)
printf("error!!! failed to created the new socket,program end here\n");
printf("OK-- you have successful created a socket named mysocket\n");
return(0); //socket 建立不成功,回初始位置
connectcheck=connect(mysocket,(struct sockaddr*)&addr_remote,sizeof(struct sockaddr));
//調(diào)用connect函數(shù)連接服務(wù)器端
if(connectcheck==-1)
printf("error!!!sorry you have failed to connect the remote server!!try again !program end here\n");
// connect不成功回初始位置
printf("OK-- Now you have successful connect the server,this server IP =%s,and it's PORT =%s,now you can communicat with this server!!!!!!!\n ",argv[1],argv[2])
//打印服務(wù)器IP地址和端口號
while(1)
bzero(gotbuffer,long);
number=recv(mysocket,gotbuffer,long,0);
//調(diào)用阻塞函數(shù)
if(number==-1)
printf("error!!! some thing wrong !let you can not got the data form server,program end here\n");
return(0);
gotbuffer[number]='\0';
close(mysocket);
3.2 服務(wù)器端程序設(shè)計(jì)
服務(wù)器端可以快速的做出客戶端的連接請求反映,服務(wù)器端反映來自客戶端的連接參數(shù),如連接的IP、連接時(shí)間、連接的當(dāng)前狀態(tài)等。服務(wù)器啟動后根據(jù)請求提供以下服務(wù):
①打開通信通道并告知本地主機(jī),在某一公認(rèn)地址上接收客戶請求;
②等待客戶請求到達(dá)該端口;
③接收到重復(fù)服務(wù)請求,處理該請求并發(fā)送應(yīng)答信號;
④返回第二步,等待另一客戶請求;
⑤關(guān)閉服務(wù)器。
服務(wù)器端程序設(shè)計(jì)的流程如圖4所示。[!--empirenews.page--]
客戶端與服務(wù)器端進(jìn)程的作用是非對稱的,因此編碼不同。同時(shí),服務(wù)器進(jìn)程一般是先于客戶請求請求而啟動的,只要系統(tǒng)運(yùn)行,該服務(wù)進(jìn)程一直存在,直到正?;驈?qiáng)迫終止。服務(wù)器端主要程序如下:
mysocket=socket(AF_INET,SOCK_STREAM,0);
//建立新的套接字
if(mysocket==-1)
printf("error!!! failed to created mysocket\n");
return(0); //socket建立不成功,回初始位置
mybindcheck=bind(mysocket,(struct sockaddr*)&addr_local,sizeof(struct sockaddr));
if(mybindcheck==-1)
printf("error!!!failed to bind the IP and port with mysocket\n");
return(0);
圖4 服務(wù)器端程序簡單示意圖
{ printf("OK--you have successed bind your IP with port %d\n",port);
listencheck=listen(mysocket,howmany);
if(listencheck==-1)
printf("error!!! you have failed listen this port,program end here\n");
return(0); //調(diào)用監(jiān)聽函數(shù)
sin_size=sizeof(struct sockaddr_in);
newsocket=accept(mysocket,(struct sockaddr*)&addr_remote,&sin_size);
//調(diào)用接收函數(shù)
if(newsocket==-1)
printf("error!!!failed to got remote connect this server,program end here\n");
return(0); //建立新的socket失敗返回
printf("OK-- now have created the newsocket to use this own connection,use this communicate with clint%s\n",inet_ntoa(addr_remote.sin_addr),port);
printf("OK-- server have successed got connect from clint IP = %s,port = %d,now connecting is running;\n",inet_ntoa(addr_remote.sin_addr),port)
pid_t pid;
pid=fork(); //調(diào)用fork()建立子進(jìn)程
if(pid>0)
printf("OK-- i am a father procces,child proccess will continue for you,it's ID= %d,now end newsock and use old socket to listen again................. \n",pid);
close(newsocket);
printf("OK-- i am a child procces,i am responsible for this new communicate,blow i will do for connect\n");
printf("OK-- please enter your data which you want to send n");
while(1)
bzero(sendbuffer,long);
scanf("%s",sendbuffer);
sendcheck=send(newsocket,sendbuffer,strlen(sendbuffer),0); //發(fā)送數(shù)據(jù)
if(sendcheck==-1)
printf("error!!!failed to send to remote\n");
close(newsocket);
else
printf("OK--now you have send %d byte data to remote!!!pleases send again!!!!\n",sendcheck);[!--empirenews.page--]
4 應(yīng)用與測試
圖5 數(shù)據(jù)發(fā)送驗(yàn)證客戶端
系統(tǒng)測試前,服務(wù)器端通過以太網(wǎng)和客戶端實(shí)現(xiàn)連接??蛻舳藰?gòu)建了linux嵌入式操作系統(tǒng),客戶端的程序通過嵌入式交叉編譯環(huán)境進(jìn)行調(diào)試。測試前應(yīng)保證網(wǎng)絡(luò)的順暢和串口的操作正常。
啟動服務(wù)器端,運(yùn)行Linux操作系統(tǒng),并建立新的用戶終端,然后運(yùn)行服務(wù)器端socket通信程序。
啟動客戶端,運(yùn)行Linux嵌入式操作系統(tǒng),配置IP地址為192.168.15.15,運(yùn)行客戶端socket通信程序。
服務(wù)器端和客戶端連接,在服務(wù)器端會有詳細(xì)的連接請求顯示出來,如IP地址、服務(wù)器當(dāng)前狀態(tài),通信模式等。服務(wù)器開始發(fā)送數(shù)據(jù),客戶端開始接收來自服務(wù)器的數(shù)據(jù),驗(yàn)證是否正確。圖5為數(shù)據(jù)發(fā)送驗(yàn)證客戶端。
5 結(jié)論
通過在PXA270中增加嵌入式操作系統(tǒng)Linux的基礎(chǔ)上實(shí)現(xiàn)一個(gè)較為簡單的網(wǎng)絡(luò)通信模塊,驗(yàn)證了嵌入式系統(tǒng)socket通行的可行性,實(shí)現(xiàn)嵌入式系統(tǒng)基于TCP/IP協(xié)議的網(wǎng)絡(luò)接入,針對各種智能設(shè)備如家用電器、工業(yè)控制裝置或儀器、安全監(jiān)控系統(tǒng)、汽車電子接入互聯(lián)網(wǎng)變得簡單容易。