0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

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

3天內(nèi)不再提示

基于TCP的Telnet服務(wù)器設(shè)計

CHANBAEK ? 來源:木南創(chuàng)智 ? 作者:尹家軍 ? 2022-12-14 15:30 ? 次閱讀

前面我們已經(jīng)實現(xiàn)了基于RAW API的TCP服務(wù)器和客戶端,也在此基礎(chǔ)上實現(xiàn)了HTTP應(yīng)用。接下來我們實現(xiàn)一個基于TCP的Telnet服務(wù)器應(yīng)用。

1 、 Telnet****協(xié)議簡介

Telnet協(xié)議是TCP/IP協(xié)議族中的一員,是Internet遠程登陸服務(wù)的標準協(xié)議和主要方式。它為用戶提供了在本地計算機上完成遠程主機工作的能力。在終端使用者的電腦上使用telnet程序,用它連接到服務(wù)器。終端使用者可以在telnet程序中輸入命令,這些命令會在服務(wù)器上運行,就像直接在服務(wù)器的控制臺上輸入一樣??梢栽诒镜鼐湍芸刂品?wù)器。要開始一個telnet會話,必須輸入用戶名和密碼來登錄服務(wù)器。Telnet是常用的遠程控制Web服務(wù)器的方法。

Telnet是位于OSI模型的第7層---應(yīng)用層上的一種協(xié)議,是一個通過創(chuàng)建虛擬終端提供連接到遠程主機終端仿真的TCP/IP協(xié)議。這一協(xié)議需要通過用戶名和口令進行認證,是Internet遠程登陸服務(wù)的標準協(xié)議。應(yīng)用Telnet協(xié)議能夠把本地用戶所使用的計算機變成遠程主機系統(tǒng)的一個終端。它提供了三種基本服務(wù):

  • Telnet定義一個網(wǎng)絡(luò)虛擬終端為遠程系統(tǒng)提供一個標準接口??蛻魴C程序不必詳細了解遠程系統(tǒng),他們只需構(gòu)造使用標準接口的程序;
  • Telnet包括一個允許客戶機和服務(wù)器協(xié)商選項的機制,而且它還提供一組標準選項;.
  • Telnet對稱處理連接的兩端,即Telnet不強迫客戶機從鍵盤輸入,也不強迫客戶機在屏幕上顯示輸出。

2 、 TELNET****服務(wù)器的設(shè)計

Telnet是一種基于TCP實現(xiàn)的遠程登錄方式,Telnet協(xié)議也分配有固定端口23,在這里我們就是用這一端口來實現(xiàn)一個Telnet服務(wù)器。這個服務(wù)器可以提供給多個客戶端訪問。

我們要實現(xiàn)的這個Telnet服務(wù)器是比較簡單的一個設(shè)計。當客戶端成功鏈接到服務(wù)器后,服務(wù)器就會提示用戶登錄,成功登陸后就可以向服務(wù)器發(fā)送命令,當發(fā)送不同的命令時,服務(wù)器給出不同的響應(yīng)。具體的操作流程設(shè)計如下:

從上面的流程圖看其實我們設(shè)計的Telnet服務(wù)器功能已經(jīng)非常明確了。但有兩點需要描述一下。首先是關(guān)于連接狀態(tài)的設(shè)定,在這里我們只是簡單的將狀態(tài)定義為兩種:已登錄和未登錄。如果已登錄則按命令交互來解析。如果未登錄則按登錄密碼來解析。

另一方面,為了實現(xiàn)命令交互,我們需要為Telnet服務(wù)器設(shè)定命令。我們簡單的設(shè)定6種命令:"hello"、"date"、"time"、"version"、"quit"與"help"等命令。事實上我們實現(xiàn)Telnet服務(wù)器主要就是處理:如何接收和響應(yīng)這些命令。

3 、 TELNET****服務(wù)器的實現(xiàn)

我們已經(jīng)設(shè)計了Telnet服務(wù)器的基本功能。接下來就是如何實現(xiàn)它了。我們已經(jīng)有前面實現(xiàn)TCP服務(wù)器的基礎(chǔ)。所以實現(xiàn)他的重點就是我們設(shè)計的Telnet服務(wù)器了。

我們依然采用實現(xiàn)普通TCP服務(wù)器結(jié)構(gòu)來實現(xiàn)Telnet服務(wù)器,只是在信息處理回調(diào)函數(shù)上更復(fù)雜一點。還有就是端口方面我們采用Telnet的慣用端口。首先必然是Telnet服務(wù)器的初始化。

1 /* TELNET服務(wù)器初始化配置*/
 2 void Telnet_Server_Initialization(void)
 3 {
 4   struct tcp_pcb *pcb;                            
 5  
 6   /* 生成一個新的TCP控制塊 */
 7   pcb = tcp_new();                                   
 8  
 9   /* 控制塊邦定到本地IP和對應(yīng)端口 */
10   tcp_bind(pcb, IP_ADDR_ANY, TCP_TELNET_SERVER_PORT);      
11  
12   /* 服務(wù)器進入偵聽狀態(tài) */
13   pcb = tcp_listen(pcb);                       
14  
15   /* 注冊服務(wù)器accept回調(diào)函數(shù) */
16   tcp_accept(pcb, TelnetServerAccept);                                       
17 }

其實初始化部分就是我們已經(jīng)熟悉的TCP服務(wù)器的初始化,只是使用了Telnet的慣用端口。接下來就是實現(xiàn)在初始化中注冊的Telnet服務(wù)器接收回調(diào)函數(shù)。該函數(shù)為tcp_accept_fn類型,注冊到了監(jiān)聽控制塊的accept字段。在服務(wù)器上有新連接建立時就會被內(nèi)核調(diào)用。

1 /* TELNET接收回調(diào)函數(shù),客戶端建立連接后,本函數(shù)被調(diào)用 */
 2 static err_t TelnetServerAccept(void *arg, struct tcp_pcb *pcb, err_t err)
 3 {    
 4   u32_t remote_ip;
 5   char linkInfo [100];
 6   u8_t iptab[4];
 7   telnet_conn_arg *conn_arg = NULL;
 8   remote_ip = pcb->remote_ip.addr;
 9  
10   iptab[0] = (u8_t)(remote_ip >> 24);
11   iptab[1] = (u8_t)(remote_ip >> 16);
12   iptab[2] = (u8_t)(remote_ip >> 8);
13   iptab[3] = (u8_t)(remote_ip);
14  
15   //生成登錄提示信息
16   sprintf(linkInfo, "Welcome to Telnet! your IP:Port --> [%d.%d.%d.%d:%d]\\r\\n", \\
17                    iptab[3], iptab[2], iptab[1], iptab[0], pcb->remote_port);  
18  
19   conn_arg = mem_calloc(sizeof(telnet_conn_arg), 1);
20   if(!conn_arg)
21   {
22     return ERR_MEM;
23   }
24  
25   conn_arg->state = TELNET_SETUP;
26   conn_arg->client_port = pcb->remote_port;
27   conn_arg->bytes_len = 0;
28   memset(conn_arg->bytes, 0, MAX_MSG_SIZE);
29  
30   tcp_arg(pcb, conn_arg);
31  
32   /* 注冊Telnet服務(wù)器連接錯誤回調(diào)函數(shù) */
33   tcp_err(pcb, TelnetServeConnectError);
34   /* 注冊Telnet服務(wù)器消息處理回調(diào)函數(shù)*/
35   tcp_recv(pcb, TelnetServerCallback);
36  
37   /* 連接成功,發(fā)送登錄提示信息 */ 
38   tcp_write(pcb, linkInfo, strlen(linkInfo), 1);
39   tcp_write(pcb, LOGIN_INFO, strlen(LOGIN_INFO), 1);
40  
41   return ERR_OK;
42 }

在這個函數(shù)中,我們實現(xiàn)的功能主要是三方面:注冊Telnet服務(wù)器消息處理回調(diào)函數(shù);注冊Telnet服務(wù)器連接錯誤回調(diào)函數(shù);初始化Telnet服務(wù)器的狀態(tài)。這個初始化是在連接建立后,Telnet服務(wù)器與客戶端的交互初始化,比如登錄狀態(tài),用戶提示等。

在上面的函數(shù)中,我們注冊了兩個回調(diào)函數(shù),接下來必然就是實現(xiàn)這兩個函數(shù)。我們先來實現(xiàn)Telnet服務(wù)器信息處理回調(diào)函數(shù)。這個函數(shù)其實就是我們前面注冊過的TCP服務(wù)器數(shù)據(jù)接收處理函數(shù)。這個函數(shù)是tcp_recv_fn類型。這是使用RAW API實現(xiàn)TCP服務(wù)器最重要的函數(shù),因為我們實現(xiàn)的TCP服務(wù)器究竟有什么功能,完全依賴于這個函數(shù)及其所調(diào)用的函數(shù)。

1 /* TELNET服務(wù)器信息處理回調(diào)函數(shù),在有消息需要處理時,調(diào)用此函數(shù) */
 2 static err_t TelnetServerCallback(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
 3 {
 4   telnet_conn_arg *conn_args = (telnet_conn_arg *)arg;
 5   char sndbuf[50];
 6   int strlen = 0;
 7   int ret = 0;
 8  
 9   if(NULL == conn_args || pcb->remote_port != conn_args->client_port)
10   {
11     if(p!= NULL)
12     {
13       pbuf_free(p);
14     }
15     return ERR_ARG;
16   }
17  
18   if (p != NULL)
19   {       
20     /* 更新接收窗口 */
21     tcp_recved(pcb, p->tot_len);
22  
23     ret = TelnetCommandInput(pcb, conn_args, p);
24  
25     if(ret == 1)//是完整命令
26     {
27       switch(conn_args->state)
28       {
29       case TELNET_SETUP:
30         {
31           if(strcmp(conn_args->bytes,PASSWORD) == 0)//密碼正確
32           {
33             strlen = sprintf(sndbuf,"##Hello! This is an LwIP-based Telnet Server##\\r\\n");
34             tcp_write(pcb, sndbuf, strlen,TCP_WRITE_FLAG_COPY);
35             strlen = sprintf(sndbuf,"##Created by Moonan...                      ##\\r\\n");
36             tcp_write(pcb, sndbuf, strlen,TCP_WRITE_FLAG_COPY);
37             strlen = sprintf(sndbuf,"##Enter help for help.  Enter quit for quit.##\\r\\n");
38             tcp_write(pcb, sndbuf, strlen,TCP_WRITE_FLAG_COPY);
39             strlen = sprintf(sndbuf,"LwIP Telnet>");
40             tcp_write(pcb,sndbuf,strlen, 1);
41  
42             conn_args->state = TELNET_CONNECTED;//轉(zhuǎn)換狀態(tài)
43           }
44           else//密碼錯誤,提示重新登錄
45           {
46             strlen = sprintf(sndbuf,"##PASSWORD ERROR! Try again:##\\r\\n");
47             tcp_write(pcb, sndbuf, strlen,TCP_WRITE_FLAG_COPY);
48           }
49           memset(conn_args->bytes, 0, MAX_MSG_SIZE);
50           conn_args->bytes_len = 0;
51           break;
52         }
53       case TELNET_CONNECTED:
54         {
55           if(TelnetCommandParse(pcb, conn_args->bytes) == 0)
56           {
57             memset(conn_args->bytes, 0, MAX_MSG_SIZE);
58             conn_args->bytes_len = 0;
59           }
60           else
61           {
62             /* 服務(wù)器關(guān)閉連接 */
63             ServerCloseTelnetConnection(pcb);
64           }
65           break;
66         }
67       default:
68         {
69           break;
70         }
71       }
72     }
73     pbuf_free(p);
74   } 
75   else if (err == ERR_OK)
76   {
77     /* 服務(wù)器關(guān)閉連接 */
78     ServerCloseTelnetConnection(pcb);
79   }
80  
81   return ERR_OK;
82  
83 }

在這個函數(shù)中,我們實現(xiàn)了Telnet服務(wù)器的各種功能,如登錄驗證,命令檢查,命令響應(yīng)等。已經(jīng)具備一個Telnet服務(wù)器的基本框架。接下來還要實現(xiàn)Telnet連接錯誤回調(diào)函數(shù)。這個函數(shù)是tcp_err_fn類型,在這個程序中主要完成連接異常結(jié)束時的一些處理,可以釋放一些必要的資源。在這個函數(shù)被內(nèi)核調(diào)用時,連接實際上已經(jīng)斷開,相關(guān)控制塊也已經(jīng)被刪除。所以在這個函數(shù)中我們可以重新初始化連接及其資源。

1 /* TELNET連接錯誤回調(diào)函數(shù),連接故障時調(diào)用本函數(shù) */
2 static void TelnetServeConnectError(void *arg, err_t err)
3 {
4   Telnet_Server_Initialization();
5 }

至此,我們就實現(xiàn)了一個簡單的Telnet服務(wù)器,當然它只是一個雛形,需要開發(fā)更復(fù)雜的功能則需要修改這幾個回調(diào)函數(shù)。

4 TELNET****服務(wù)器總結(jié)

我們已經(jīng)實現(xiàn)了一個簡單的Telnet服務(wù)器。當然,我們的目的主要是以此來學(xué)習(xí)基于LwIP的復(fù)雜的TCP應(yīng)用。事實上理解了TCP服務(wù)器的實現(xiàn)機制,諸如此類基于TCP的高級應(yīng)用協(xié)議并不是特別復(fù)雜的事情。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    12

    文章

    9149

    瀏覽量

    85402
  • HTTP
    +關(guān)注

    關(guān)注

    0

    文章

    505

    瀏覽量

    31218
  • TCP
    TCP
    +關(guān)注

    關(guān)注

    8

    文章

    1353

    瀏覽量

    79068
  • TELNET
    +關(guān)注

    關(guān)注

    0

    文章

    16

    瀏覽量

    10786
收藏 人收藏

    評論

    相關(guān)推薦

    串口服務(wù)器——TCP Server

    如何讓自動化領(lǐng)域的串口設(shè)備具備聯(lián)網(wǎng)能力?本文將基于EsDA平臺,帶你開發(fā)一個串口服務(wù)器TCP服務(wù)器的業(yè)務(wù),快速實現(xiàn)串口聯(lián)網(wǎng)功能。簡介隨著物聯(lián)網(wǎng)技術(shù)的發(fā)展,串口通信和TCP/IP通信業(yè)
    的頭像 發(fā)表于 07-31 17:58 ?1648次閱讀
    串口<b class='flag-5'>服務(wù)器</b>——<b class='flag-5'>TCP</b> Server

    tcp方式連接不了服務(wù)器了,服務(wù)器代碼還能開源嗎?

    是在維護服務(wù)器嗎?已經(jīng)兩天了。http方式還可以連接上,就tcp的方式不行了.服務(wù)器代碼能開源嗎?讓我們自己搭建服務(wù)器用。
    發(fā)表于 07-15 06:53

    電腦技術(shù)交流【<vista下如何找回telnet服務(wù)器>】

    遠程登錄為用戶提供了在本地計算機上完成遠程主機的能力。在最終用戶的計算機上使用Telnet程序,用它來連接到服務(wù)器。電腦城裝機版的小編今天跟大家分享Vista系統(tǒng)中使用Telnet服務(wù)器
    發(fā)表于 08-26 09:02

    telnet連接自己寫的socket服務(wù)器后退出telnet顯示段錯誤

    在Linux中自己用tcp寫的服務(wù)器,用telnet連接socket服務(wù)器后,在退出telnet服務(wù)器
    發(fā)表于 11-24 00:36

    啟用了TCP/IP命令和Telnet服務(wù)器選項只有LED閃爍

    ,因此通過MHC,我啟用了TCP/IP命令和Telnet服務(wù)器選項。只有LED閃爍。同樣,使用MHC,我禁用了上述兩個選項,我生成了新代碼,我順利地編譯了項目,并將演示下載到板上,一切恢復(fù)正常操作。關(guān)于這個問題,有什么想法或建議
    發(fā)表于 09-11 09:18

    tcp服務(wù)器怎么關(guān)閉?

    我在f407上開了一個tcp_server,可以用客戶端連接上,但是用tcp_close關(guān)閉后,還能鏈接上服務(wù)器。是什么原因。 或者如何把這個服務(wù)器關(guān)閉了。
    發(fā)表于 03-30 03:27

    TCP服務(wù)器創(chuàng)建過程

    用過正點原子LWIP服務(wù)器例程開發(fā)的朋友可能知道,例程的設(shè)計是只支持一個客戶端連接的,但實際應(yīng)用中往往需要用到多客戶端連接。下面是在正點原子擴展例程網(wǎng)絡(luò)實驗14 NETCONN_TCP 服務(wù)器
    發(fā)表于 08-24 08:03

    TCP服務(wù)器模式配置流程是什么

    TCP服務(wù)器模式配置流程是什么?如何去實現(xiàn)TCP服務(wù)器通信呢?
    發(fā)表于 01-14 06:02

    如何使用tcp連接自己搭建的服務(wù)器?

    大家好,我想使用tcp連接自己搭建的服務(wù)器 這個服務(wù)器不是本地local的IP4而是有域名的,類似espslr.*****.com,端口是8591 我使用examples\protocols
    發(fā)表于 03-07 06:58

    如何將文件上傳到NodeMCU ESP8266 telnet服務(wù)器

    您好, 我只想與您分享一個簡單的 bash 腳本,用于在運行 telnet 服務(wù)器時將文件上傳到 ESP8266。當我懶得親自訪問我的設(shè)備但仍想上傳更新的腳本時,它對我很有幫助。 目標與源文件具有
    發(fā)表于 04-28 08:27

    telnet.lua telnet服務(wù)器示例問題求解

    如果我在串行控制臺寫 =wifi.sta.getip() 我得到 IP 掩碼網(wǎng)關(guān) 如果我使用 telnet.lua 服務(wù)器示例并鍵入相同的命令我只得到 IP 經(jīng)過一些測試我發(fā)現(xiàn)在串行控制臺我得到
    發(fā)表于 05-09 11:34

    HTTP服務(wù)器使用uIP TCP/ IP堆棧的示例

    應(yīng)用程序: HTTP 服務(wù)器使用 uIP TCP/ IP 堆棧的示例 BSP 版本:M480系列BSP CMSIS V3.03.001 硬件: NuMaker-PFM-M487 VER 3.0
    發(fā)表于 08-22 07:07

    RAW API 接口的TCP服務(wù)器

    RAW Tcp回響服務(wù)器
    的頭像 發(fā)表于 07-05 00:10 ?3841次閱讀
    RAW API 接口的<b class='flag-5'>TCP</b><b class='flag-5'>服務(wù)器</b>

    基于LwIP的TCP服務(wù)器設(shè)計

    前面我們實現(xiàn)了UDP服務(wù)器及客戶端以及基于其上的TFTP應(yīng)用服務(wù)器。接下來我們將實現(xiàn)同樣廣泛應(yīng)用的TCP協(xié)議各類應(yīng)用。
    的頭像 發(fā)表于 12-14 15:09 ?1682次閱讀
    基于LwIP的<b class='flag-5'>TCP</b><b class='flag-5'>服務(wù)器</b>設(shè)計

    【EsDA應(yīng)用】串口服務(wù)器——TCP Server

    如何讓自動化領(lǐng)域的串口設(shè)備具備聯(lián)網(wǎng)能力?本文將基于EsDA平臺,帶你開發(fā)一個串口服務(wù)器TCP服務(wù)器的業(yè)務(wù),快速實現(xiàn)串口聯(lián)網(wǎng)功能。 ?? 簡介 隨著物聯(lián)網(wǎng)技術(shù)的發(fā)展,串口通信和TCP/
    的頭像 發(fā)表于 06-14 11:40 ?796次閱讀
    【EsDA應(yīng)用】串口<b class='flag-5'>服務(wù)器</b>——<b class='flag-5'>TCP</b> Server