衡阳派盒市场营销有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何理解TCP客戶端通信

單片機愛好者 ? 2019-09-17 09:07 ? 次閱讀

上一節說了UDP,這一節就聊聊TCP,畢竟它倆經常同時出現。優缺點上一節也提了一下:安全性好,速度慢。

除了這兩點,還有就是:

TCP通信之前是需要建立連接的,如同打電話之前先撥號一樣,而UDP無連接;

TCP只能一對一通信,UDP不止一對一,還支持一對多;

TCP對系統資源要求更多,UDP相對少一些。

所以兩者各有優缺點,大家在選擇通信協議的時候一定要根據自己的實際情況來確定。

然后就是客戶端,這是啥?和它伴隨的,還有一個詞經常出現,就是:服務器端。這兩者又是什么關系?

基本上,這兩者在TCP通信過程中,都是結伴出現的。以瀏覽器為例,它就是一個客戶端,當我們想上網的時候,輸入一個網址。瀏覽器會根據我們輸入的網址向相應的服務器端發出請求,然后服務器端返回相應的網頁給瀏覽器。這就是它們的應用場景之一。

所以,在TCP通信過程中,一般都是由客戶端發起請求,服務器端相應請求。

那么,在windows/linux下,是如何進行這方面的編程的?步驟如下(參考百度):

TCP編程的服務器端一般步驟是:

1、創建一個socket,用函數socket();

2、設置socket屬性,用函數setsockopt(); * 可選

3、綁定IP地址、端口信息到socket上,用函數bind();

4、開啟監聽,用函數listen();

5、接收客戶端上來的連接,用函數accept();

6、收發數據,用函數send()和recv(),或者read()和write();

7、關閉網絡連接;

8、關閉監聽;

TCP編程的客戶端一般步驟是:

1、創建一個socket,用函數socket();

2、設置socket屬性,用函數setsockopt();* 可選

3、綁定IP地址、端口等信息到socket上,用函數bind();* 可選

4、設置要連接的對方的IP地址和端口等屬性;

5、連接服務器,用函數connect();

6、收發數據,用函數send()和recv(),或者read()和write();

7、關閉網絡連接;

可以看到,從第四步開始,客戶端和服務器端的工作內容有了不一樣。

socket是啥?

簡單來說,是個函數,用來創建套接字。

那么,套接字又是什么鬼?

為了防止本篇日志閑扯太多,我盡量簡單說,根據字面意思,socket字面意思是(電源)插座,而套接字本質上是一種網絡編程接口,用來完成兩個應用程序之間的數據傳輸。你把設備插頭插到電源插座上,設備通上電了,同理,你把應用程序的端口插到socket里,數據就通上了。

注:因為本人是硬件出身,所以對這些協議的理解全靠百度和工作積累,如果有表達錯誤的,歡迎指正。

這一節先在8266上面寫一個客戶端的程序,咱們看一下實現的效果。跟上一節一樣,還是要借助一個網絡調試助手。同時,本節代碼都是在上一節基礎上修改來的,所以,如果上一節看懂了,這一節就很好理解,反之,你懂的~

先說步驟,依然很多,參考上面提到的“TCP編程的客戶端一般步驟”,這里大致分為7步:

1 包含頭文件

#include "espconn.h"

#include "mem.h"

主要是"espconn.h",涉及到TCP通訊所需的各種數據結構。上一節已經包含了,可以略過。

2 設置工作模式為station+ soft-ap模式,連接到當前環境下的wifi

因為前幾步跟上一節一模一樣,所以整合了一下:

wifi_set_opmode(0x03); // station+ soft-ap模式

struct softap_config config; //定義AP參數結構體,

wifi_softap_get_config(&config); //獲取當前AP模式的參數

os_memcpy(config.ssid,"ESP8266",strlen("ESP8266"));

//修改AP名稱

os_memcpy(config.password,"123456789",strlen("123456789"));

//修改AP密碼

config.ssid_len=strlen("ESP8266"); //修改 AP名稱的長度

wifi_softap_set_config(&config); //使修改后的參數生效

然后連到我家wifi,你們要改成你們家里或者辦公室里的wifi。

3 確定TCP連接的參數

這里要確定幾點:你是誰?你要和誰連接?連接的端口是多少?

你是誰——ESP8266,8266連接家里路由成功之后,會自動獲得一個IP,這是客戶端IP

你要和誰連接——因為是在我電腦上使用網絡調試助手模擬TCP服務器端,所以服務器端的IP是我電腦的IP:192.168.1.103

連接的端口——長話短說,TCP連接的端口從0到65535都有,但一般0~1023是公有的,從1024開始往后,可以選為自己的端口。這里選1024.

struct ip_info info;

const char remote_ip[4]={192,168,1,103}; //TCP服務端IP

wifi_get_ip_info(STATION_IF,&info); //獲取8266的WIFI信息

tcp_client_init((struct ip_addr *)remote_ip,&info.ip,1024);

4 TCP客戶端初始化

其實就是第三步里面的tcp_client_init函數,咱們主要看一下函數內部實現的功能。首先是在client.h文件中定義了一個espconn格式的結構體:

struct espconn user_tcp_conn; //對應網絡連接的結構體

然后在tcp_client_init函數中,對結構體的各個部分進行配置:

{

//TCP通信時,對應的espconn參數配置

user_tcp_conn.type=ESPCONN_TCP;

user_tcp_conn.state=ESPCONN_NONE;

user_tcp_conn.proto.tcp=(esp_tcp *)os_zalloc(sizeof(esp_tcp));

os_memcpy(user_tcp_conn.proto.tcp->local_ip,local_ip,4);

os_memcpy(user_tcp_conn.proto.tcp->remote_ip,remote_ip,4);

user_tcp_conn.proto.tcp->local_port=espconn_port();

user_tcp_conn.proto.tcp->remote_port=remote_port;

//注冊連接回調函數和重連回調函數

espconn_regist_connectcb(&user_tcp_conn,user_tcp_connect_cb);

espconn_regist_reconcb(&user_tcp_conn,user_tcp_recon_cb);

//啟用連接

espconn_connect(&user_tcp_conn);

}

函數中可以看到,espconn的參數設置完成之后,注冊了兩個回調函數,連接完成回調函數(連接完成以后,你想干嘛?)和重連回調函數(重連的時候,該咋辦?):

espconn_regist_connectcb(&user_tcp_conn,user_tcp_connect_cb);

espconn_regist_reconcb(&user_tcp_conn,user_tcp_recon_cb);

最后,開始TCP連接:

espconn_connect(&user_tcp_conn); //連接TCP server,連接成功返回0.

5 定義連接成功的回調函數

void ICACHE_FLASH_ATTR user_tcp_connect_cb(void *arg){

struct espconn *pespconn=arg;

espconn_regist_recvcb(pespconn,user_tcp_recv_cb);

espconn_regist_sentcb(pespconn,user_tcp_sent_cb);

espconn_regist_disconcb(pespconn,user_tcp_discon_cb);

espconn_sent(pespconn,"hello,this is esp8266!",strlen("hello,this is esp8266!"));

}

函數內部進行了幾個操作:

注冊接收完成的回調函數:接收完成以后,你想做點啥~

注冊發送完成的回調函數:發送完成以后,你想做點啥~

注冊斷開TCP連接的回調函數:斷開TCP連接以后,你想做點啥~

TCP連接下,發送數據:hello,this is esp8266!

6 定義user_tcp_connect_cb函數內部注冊的回調函數

這里先說一下,基本上從上一節開始,代碼的編寫就進入了回調函數套回調函數的情形。如果是沒接觸過回調函數的,剛開始看肯定有些別扭。但如果適應以后,你會發現這樣操作還是很方便的。

因為每個回調函數,在手冊里都有說明,功能、參數、返回值,都很清晰。基本上只要看著手冊和官方SDK里的例程,大部分問題都能解決。

//接收完成回調函數,把收到的數據打印出來,延時,斷開連接

void ICACHE_FLASH_ATTR user_tcp_recv_cb(void *arg,

char *pdata,

unsigned short len){

os_printf("receive data:%s ",pdata);

os_delay_us(300);

espconn_disconnect((struct espconn *)arg);

}

//發送完成回調函數,打印發送完成標志

void ICACHE_FLASH_ATTR user_tcp_sent_cb(void *arg){

os_printf("send success!");

}

//斷開TCP連接的回調函數,打印相關信息

void ICACHE_FLASH_ATTR user_tcp_discon_cb(void *arg){

os_printf("disconnect success!");

}

7 定義TCP重連的回調函數

在第4步里注冊了兩個回調函數,一個是連接成功的回調函數,第5步已經說了。另一個就是重連的回調函數:

//如果連接錯誤,打印一下故障碼,然后重新連接

void ICACHE_FLASH_ATTR user_tcp_recon_cb(void *arg, sint8 err){

os_printf("error,error code is%d ",err);

espconn_connect((struct espconn *)arg);

}

好,到此為止,程序修改完畢。

注:本例程里提到的大部分函數,都參照手冊2c-esp8266_sdk_api_guide_cn_v1.5.4。

再說一點,很多函數定義的時候,后面會跟一個參數:void *arg,這是什么?

以第5步里注冊回調函數為例:

espconn_regist_recvcb(pespconn,user_tcp_recv_cb);

注冊了user_tcp_recv_cb函數,這個函數在定義的時候就有如下幾個參數

(void *arg,char *pdata,unsigned short len)

從哪來的?

打開手冊2c-esp8266_sdk_api_guide_cn_v1.5.4,查找espconn_regist_recvcb函數,可以看到如下說明;

根據其中的espconn_recv_callback,咱們繼續向下找:

至此,可以看到相關參數已經在回調函數的格式里定義好了,咱們只需要照著寫就行。

程序修改完成,保存、清理、編譯、下載一條龍,然后重新上電。這里,需要借助串口助手和網絡調試助手兩個工具來查看效果。效果如下所示:

設置網絡調試助手:

可以看到,在網絡調試助手上,分別顯示了client上線的時間和發來的數據。如果這時候咱們手動給client發一個數據:mcu lover。

可以在串口助手上看到:

顯示了收到的數據,最后斷開TCP連接。

至此,TCP客戶端通信說完了。還是希望大家多動手,畢竟這類東西要動手才有收獲。后面會說一下TCP服務器端的用法(跟這個差不多),然后是POST和GET的用法,再然后,就可以根據GET,搞一個天氣預報的小應用,相信很多人會比較感興趣。

最后嘮叨一下,這篇日志寫的比較痛苦,因為我是從一個硬件工程師的視角去說這些東西,所以希望跟我類似的人能比較好的理解日志中出現的這些網絡協議。因為通常來說,搞硬件的就是搞硬件,畫畫PCB、搞搞焊接、給單片機寫寫程序,甚至再寫一寫上位機,在linux下寫一些應用。至于說整天研究TCP/UDP,或者POST、GET,比較少,或者說不算硬件工程師/單片機工程師的范疇了。

但是物聯網芯片的出現打破了這一屏障,它小巧,單片機級別的資源就能使用;但它又強大,可以聯網,實現各種網絡通信。所以,我們要不停的學習,千萬不要自我滿足。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • TCP
    TCP
    +關注

    關注

    8

    文章

    1378

    瀏覽量

    79301
  • TCP通信
    +關注

    關注

    0

    文章

    146

    瀏覽量

    4292

原文標題:ESP8266_12 ESP8266客戶端模式下的TCP通信

文章出處:【微信號:gh_dae0718828df,微信公眾號:gh_dae0718828df】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux網絡編程-TCP客戶端如何獲取要連接的服務IP?

    本篇介紹了在TCP通信中,客戶端通過UDP廣播,實現自動獲取服務的IP地址,并進行TCP連接的具體方法,并通過代碼實現,來測試此方案是實際
    的頭像 發表于 09-27 08:56 ?3897次閱讀
    Linux網絡編程-<b class='flag-5'>TCP</b><b class='flag-5'>客戶端</b>如何獲取要連接的服務<b class='flag-5'>端</b>IP?

    如何同時在ESP8266上運行TCP客戶端TCP服務?

    我們是 esp8266 的長期用戶,并在該芯片上運行數千臺家庭自動化類別的現場設備。然而,一個小小的限制阻礙了我們開發一些更有趣和創新的產品。 要求:我們需要同時運行 TCP 客戶端(連接
    發表于 07-08 08:26

    labview TCP客戶端

    最近在做一個labview 客戶端測試小程序,服務器采用MFC編寫,客戶端采用TCP偵聽函數,通信可以連接,數據也正確,但是服務器檢測發送
    發表于 06-30 23:15

    【NanoPi NEO試用體驗】TCP通信客戶端程序

    寫了一個TCP通信客戶端程序,匆忙之間寫的,不夠完善,可以圍觀,給出精辟的見解。百度百科TCP/IP介紹:http://baike.baidu.com/link?url
    發表于 12-28 23:40

    TCP通信時服務如何接收客戶端的數據?

    畢設采用的是TCP協議,組員做的是下位機,C編程,WiFi模塊工作處于客戶端。我負責上位機,Labview使用tcp協議時服務怎么接收客戶端
    發表于 04-14 14:49

    基于Socket開發TCP傳輸客戶端

    1 程序界面設計 TCP客戶端在上位機開發中應用很廣,大多數情況下,上位機軟件都是作為一個TCP客戶端來與PLC或其他服務器進行通信的。
    發表于 07-02 06:33

    stm32f107vc lwip tcp客戶端

    stm32f107vc lwip tcp客戶端 服務器數據傳輸第一篇TCP客戶端模式簡單數據收發 ----控制開發板LED燈概要建立LWIP客戶端
    發表于 08-06 09:17

    當WiFi信號變低時,服務器和客戶端之間的TCP通信丟失,如何使客戶端重新連接?

    大家好, 當 WiFi 信號變低時,服務器和客戶端之間的 TCP 通信丟失,比如超過 -80dBm。一旦客戶端斷開連接,它就無法重新連接并正常進行
    發表于 05-15 07:31

    服務器和客戶端之間的TCP通信丟失怎么處理?

    嗨, 當 WiFi 信號變低時,比如超過 -80dBm,我面臨服務器和客戶端之間的 TCP 通信丟失。一旦客戶端斷開連接,它就無法重新連接并正常進行
    發表于 05-16 08:19

    JAVA教程之TCP客戶端

    JAVA教程之TCP客戶端,很好的JAVA的資料,快來學習吧
    發表于 04-11 17:28 ?7次下載

    TCP回響客戶端:RAW API接口

    TCP回響客戶端例程(RAW API)
    的頭像 發表于 07-05 00:31 ?3986次閱讀
    <b class='flag-5'>TCP</b>回響<b class='flag-5'>客戶端</b>:RAW API接口

    網絡調試和串口調試集合UDP TCP客戶端TCP服務器應用程序免費下載

    本文檔的主要內容詳細介紹的是網絡調試和串口調試集合UDP TCP客戶端TCP服務器應用程序免費下載。
    發表于 08-30 08:00 ?16次下載
    網絡調試和串口調試集合UDP <b class='flag-5'>TCP</b><b class='flag-5'>客戶端</b>和<b class='flag-5'>TCP</b>服務器<b class='flag-5'>端</b>應用程序免費下載

    Linux下網絡編程TCP并發服務器和TCP客戶端程序免費下載

    本文檔的主要內容詳細介紹的是Linux下網絡編程TCP并發服務器和TCP客戶端程序免費下載
    發表于 01-08 15:12 ?9次下載
    Linux下網絡編程<b class='flag-5'>TCP</b>并發服務器和<b class='flag-5'>TCP</b><b class='flag-5'>客戶端</b>程序免費下載

    Linux下TCP網絡編程-創建服務器與客戶端

    這篇文章介紹在Linux下的socket編程,完成TCP服務器、客戶端的創建,實現數據通信
    的頭像 發表于 08-14 09:26 ?2550次閱讀
    Linux下<b class='flag-5'>TCP</b>網絡編程-創建服務器與<b class='flag-5'>客戶端</b>

    基于LwIP的TCP客戶端設計

    上一篇我們基于LwIP協議棧的RAW API實現了一個TCP服務器的簡單應用,接下來一節我們來實現一個TCP客戶端的簡單應用。
    的頭像 發表于 12-14 15:12 ?2350次閱讀
    基于LwIP的<b class='flag-5'>TCP</b><b class='flag-5'>客戶端</b>設計
    百家乐现场网络| 百家乐如何稳赢| 冠军娱乐城| 怎么玩百家乐的玩法技巧和规则 | 足球皇冠大全| 百家乐赌博合作| 宝马百家乐官网的玩法技巧和规则 | 百家乐赢钱lv| 百家乐官网赌博经历| 蜀都棋牌游戏大厅| 百家乐代理荐| 百家乐官网必赢法冯耘| 双牌县| 玩百家乐会犯法吗| 博彩百家乐官网字谜总汇| 浦东新区| 易胜博网站| 大发888信誉| 南宁百家乐的玩法技巧和规则| 做生意摆放风水| 路单百家乐官网的玩法技巧和规则 | 362娱乐城开户| 全讯网vc8888| 澳门百家乐技巧| 百家乐洗码软件| 24山64卦分金| 澳博国际| 珠江太阳城广场| 北京太阳城老年公寓| 大发888 代充| 百家乐官网投注开户| 百家乐官网园sun811| 杨筠松 24山 土| 百家乐太阳城真人游戏| 大发888出纳柜台 在线| 百家乐官网长玩必输| 闲和庄百家乐官网的玩法技巧和规则 | 济州岛百家乐的玩法技巧和规则| 澳门顶级赌场娱乐平台| 百家乐牌具公司| 盛世国际娱乐城|