使用Rainbow開發(fā)包的TCP/IP協(xié)議棧,除了可以做TCP客戶端外,還可以作為服務(wù)端,接受客戶端連接并進行數(shù)據(jù)交互。我們先來看看軟件運行的效果:將本文的程序進行編譯、燒寫到Rainbow中,將USB-TTL與電腦連接(這個不是必須的),將網(wǎng)線插入網(wǎng)絡(luò)接口,按下Rainbow復(fù)位鍵,在串口、網(wǎng)絡(luò)通用調(diào)試工具中我們將看到:
表明此時Rainbow作為網(wǎng)絡(luò)服務(wù)器已經(jīng)啟動,我們在網(wǎng)絡(luò)設(shè)置區(qū)域選擇作為客戶端、并設(shè)置正確的服務(wù)器(Rainbow)IP地址、端口,然后點擊“connect”按鈕,此時將會在網(wǎng)絡(luò)接收數(shù)據(jù)區(qū)域顯示一個菜單:
在網(wǎng)絡(luò)發(fā)送的輸入?yún)^(qū)域輸入0,然后按“send”,板子上的LED便會熄滅;輸入1,然后按“send”,LED又會被點亮。
在軟件包的“Projects\TCP-Server”文件夾包含了本文的完整工程,可以直接編譯、燒寫和調(diào)試。這個程序主要展示如何通過TCP向服務(wù)器端發(fā)送字符串,看看main.cpp的代碼:
#include "WProgram.h"
#include "Ethernet.h"
#include "EthernetServer.h"
#include "EthernetClient.h"
//定義客戶端通過TCP協(xié)議控制LED亮和滅的管腳
#define LED_PIN PC13
//網(wǎng)絡(luò)模塊的MAC地址
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//網(wǎng)絡(luò)模塊的IP地址
IPAddress ip(192, 168, 1, 15);
//在6000進行監(jiān)聽
EthernetServer server(6000);
//連接成功后標識設(shè)置為true
bool connectFlag = false;
void setup()
{
//初始化Rainbow
boardInit();
//初始化默認串口
Serial.begin();
Serial.println("TCP-Server start...");
//對網(wǎng)絡(luò)進行初始化
Ethernet.begin(mac, ip);
//開始進行監(jiān)聽
server.begin();
//使用LED作為指示,客戶端發(fā)送on的時候LED發(fā)光;發(fā)送off的時候LED熄滅
pinMode(LED_PIN, GPIO_Mode_Out_PP);
}
void loop()
{
//取得客戶端socket對象
EthernetClient client = server.available();
//是否和客戶端正確握手
if(client.connected())
{
if(connectFlag)
{
//客戶端是否傳來數(shù)據(jù)
client.parsePacket();
while(client.available() > 0)
{
//設(shè)置超時時間,這個時間主要用于readString()來判斷是否有數(shù)據(jù)輸入,如果在10ms沒有數(shù)據(jù)輸入則認為數(shù)據(jù)輸入完畢,默認是1s
client.setTimeout(10);
String msg = client.readString();
//根據(jù)客戶端輸入的數(shù)據(jù)點亮或關(guān)閉LED
if(msg == "1")
digitalWrite(LED_PIN, LOW);
else if(msg == "0")
digitalWrite(LED_PIN, HIGH);
}
}
else
{
//握手成功,輸出操作菜單
connectFlag = true;
String menuStr = "請輸入操作指令:\r\n";
menuStr += "1 - 開燈\r\n";
menuStr += "0 - 關(guān)燈\r\n";
client.print(menuStr);
}
}
else if(connectFlag)
{
connectFlag = false;
}
}
int main()
{
setup();
while(1) loop();
}
在Rainbow中對TCP服務(wù)端編程和客戶端一樣簡單,按照以下步驟進行:
1、定義TCP服務(wù)端對象,在定義對象的時候需要指定監(jiān)聽的端口號:EthernetServer server(6000);
2、開始進行監(jiān)聽:server.begin();
3、獲取客戶端socket對象:EthernetClient client = server.available();
4、通信前需要判斷與客戶端是否成功握手:client.connected(),成功握手返回true
5、與客戶端進行網(wǎng)絡(luò)通信。在接收客戶端傳來的數(shù)據(jù)之前需要調(diào)用client.parsePacket(),然后調(diào)用client.available()可以返回客戶端發(fā)來的數(shù)據(jù)量,接下來可以使用EthernetClient提供的各種讀寫方法從網(wǎng)絡(luò)上讀寫數(shù)據(jù),EthernetClient是Stream的子類,具體讀寫方法參見Stream類