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

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

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

有線網(wǎng)絡(luò)通信實(shí)驗(yàn)3之TCP客戶端

汽車電子技術(shù) ? 來源:滑小稽筆記 ? 作者:電子技術(shù)園地 ? 2023-03-01 14:27 ? 次閱讀

26.1 TCP協(xié)議概述

TCP是一種面向連接的,可靠地,基于IP的傳輸層協(xié)議,面向連接就意味著兩個(gè)實(shí)用TCP的應(yīng)用在進(jìn)行數(shù)據(jù)交換的時(shí)候必須先建立一個(gè)TCP連接,當(dāng)應(yīng)用層向TCP層發(fā)送用于傳輸?shù)?,?位字節(jié)表示的數(shù)據(jù)流,TCP先把數(shù)據(jù)流分割成適當(dāng)長(zhǎng)度的報(bào)文段,最大傳輸段的長(zhǎng)度MSS通常受計(jì)算機(jī)連接的網(wǎng)絡(luò)的數(shù)據(jù)鏈路層的最大傳輸單元MTU控制,之后TCP才把數(shù)據(jù)包傳給IP層,通過它來將數(shù)據(jù)傳送給接收端的TCP層。為了保證報(bào)文傳輸?shù)目煽啃?,?huì)給每個(gè)包一個(gè)序號(hào),同時(shí)序號(hào)也保證了傳送到接收端的數(shù)據(jù)報(bào)文能被按照順序接收,然后接收端對(duì)成功接收的報(bào)文發(fā)回一個(gè)響應(yīng)的確認(rèn)ACK,如果傳送端在合理的時(shí)間RTT內(nèi)沒有收到確認(rèn),那么對(duì)應(yīng)的數(shù)據(jù)就會(huì)被重傳TCP在數(shù)據(jù)正確性和合法性上采用一個(gè)校驗(yàn)和函數(shù)來測(cè)定數(shù)據(jù)是否有錯(cuò)誤,在發(fā)送和接收時(shí)都必須計(jì)算校驗(yàn)和,在保證可靠性上,對(duì)于窗口內(nèi)未經(jīng)確認(rèn)的分組需要重傳報(bào)文,在擁塞控制上,采用TCP擁塞控制算法。

TCP數(shù)據(jù)被封裝在一個(gè)IP數(shù)據(jù)報(bào)文中,IP數(shù)據(jù)報(bào)文結(jié)構(gòu)如下圖所示。

圖片

TCP報(bào)文數(shù)據(jù)格式在沒有選項(xiàng)的情況下,通常是20個(gè)字節(jié),數(shù)據(jù)結(jié)構(gòu)如下圖所示

圖片

(1)源端口號(hào)和目的端口號(hào)用于尋找發(fā)送端和接收端的應(yīng)用進(jìn)程,這個(gè)與UDP報(bào)文相同,這兩個(gè)值加上IP首部中的源IP地址和目的IP地址唯一確定了一個(gè)TCP連接。

(2)序列號(hào)字段用來標(biāo)識(shí)從TCP發(fā)送端向TCP接收端發(fā)送的數(shù)據(jù)字節(jié)流,用于表示在這個(gè)報(bào)文段中的第一個(gè)數(shù)據(jù)字節(jié),當(dāng)建立一個(gè)新的連接時(shí),握手報(bào)文中的SYN標(biāo)志置1,這個(gè)握手報(bào)文中的序號(hào)字段為隨機(jī)選擇的初始序號(hào)ISN(Initial Sequence Number),當(dāng)連接建立好以后發(fā)送方要發(fā)送的第一個(gè)字節(jié)序號(hào)為ISN+1。

(3)確認(rèn)號(hào)字段只有在ACK為1的時(shí)候才有用,確認(rèn)號(hào)中包含發(fā)送確認(rèn)的一方所期望接收到的下一個(gè)序號(hào),確認(rèn)號(hào)是在上一次成功接收到的數(shù)據(jù)字節(jié)序列號(hào)上加1,例如上次接收成功接收到對(duì)方發(fā)過來的數(shù)據(jù)序號(hào)為X,那么返回的確認(rèn)號(hào)就應(yīng)該為X+1

(4)頭部長(zhǎng)度又稱為首部長(zhǎng)度,首部長(zhǎng)度中給出了首部的長(zhǎng)度,以4個(gè)字節(jié)為單位,這個(gè)字段有4bit,因此TCP最多有60字節(jié)的首部,如果沒有任何的選項(xiàng)字段,正常的首部長(zhǎng)度是20字節(jié),TCP首部中還有6個(gè)標(biāo)志位,這6個(gè)標(biāo)志位如下表所示。

標(biāo)志位 說明
URG 置1時(shí)表示緊急指針有效
ACK 置1時(shí)表示確認(rèn)序號(hào)字段有效
PSH 置1表示接收方應(yīng)該盡快將這個(gè)報(bào)文段交給應(yīng)用層
RST 置1表示重建連接
SYN 用于發(fā)起連接
FIN 發(fā)送端完成發(fā)送任務(wù),終止連接

(5)窗口尺寸也就是窗口大小,其中填寫相應(yīng)的值以通知對(duì)方期望接收的字節(jié)數(shù),窗口大小字段是TCP流量控制的關(guān)鍵字段,窗口大小是一個(gè)2個(gè)字節(jié)的字段,因此窗口大小最大為65535個(gè)字節(jié)。

(6)16位校驗(yàn)和和UDP的校驗(yàn)和計(jì)算原理相同,這是一個(gè)強(qiáng)制性的字段,校驗(yàn)和覆蓋整個(gè)TCP報(bào)文段。

(7)緊急指針只有在URG置1時(shí)有效,是一個(gè)正偏移量,和序號(hào)字段中的值相加表示緊急數(shù)據(jù)最后一個(gè)字節(jié)的序號(hào)。

tcp.c,tcp.h,tcp_in.c和tcp_out.c是LWIP中關(guān)于TCP協(xié)議的文件,TCP層中函數(shù)的關(guān)系如下圖所示。

圖片

常用的TCP協(xié)議的API函數(shù)如下表所示。

函數(shù)類型 API函數(shù) 功能
建立TCP連接 tcp_new() 創(chuàng)建一個(gè)TCP的PCB控制塊
tcp_bind() 為TCP的PCB控制塊綁定一個(gè)本地IP地址和端口號(hào)
tcp_listen() 開始TCP的PCB監(jiān)聽
tcp_accept() 控制塊accept字段注冊(cè)的回調(diào)函數(shù),偵聽到連接時(shí)被調(diào)用
tcp_accepted() 通知LWIP協(xié)議棧一個(gè)TCP連接被接受了
tcp_conect() 連接遠(yuǎn)端主機(jī)
TCP數(shù)據(jù)發(fā)送 tcp_write() 構(gòu)造一個(gè)報(bào)文并放在控制塊的發(fā)送隊(duì)列緩沖中
tcp_sent() 控制塊sent字段注冊(cè)的回調(diào)函數(shù),數(shù)據(jù)發(fā)送成功后被回調(diào)
tcp_output() 將發(fā)送緩沖隊(duì)列中的數(shù)據(jù)發(fā)送出去
TCP數(shù)據(jù)接收 tcp_recv() 控制塊recv字段注冊(cè)的回調(diào)函數(shù),當(dāng)接收到新數(shù)據(jù)時(shí)被調(diào)用
tcp_recved() 當(dāng)程序處理完數(shù)據(jù)后一定要調(diào)用這個(gè)函數(shù),通知內(nèi)核更新接收窗口
數(shù)據(jù)輪詢 tcp_poll() 控制塊poll字段注冊(cè)的回調(diào)函數(shù),該函數(shù)周期性調(diào)用
關(guān)閉和終止連接 tcp_close() 關(guān)閉TCP連接
tcp_err() 控制塊err字段注冊(cè)的回調(diào)函數(shù),遇到錯(cuò)誤時(shí)被調(diào)用
tcp_abort() 中斷TCP連接

26.2 應(yīng)用編寫

26.2.1 tcp_client.c代碼編寫

#include "tcp_client.h"
#include "delay.h"
#include "usart1.h"
#include "lcd.h"
#include "malloc.h"
#include "string.h"
#include "comm.h"
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/memp.h"
#include "lwip/mem.h"
//TCP Client 測(cè)試全局狀態(tài)標(biāo)記變量
//bit7:0,沒有數(shù)據(jù)要發(fā)送;1,有數(shù)據(jù)要發(fā)送
//bit6:0,沒有收到數(shù)據(jù);1,收到數(shù)據(jù)了
//bit5:0,沒有連接上服務(wù)器;1,連接上服務(wù)器了
//bit4~0:保留
u8 tcp_client_flag;   
//設(shè)置遠(yuǎn)端IP地址
void tcp_client_set_remoteip()
{
  u8 *tbuf;
  tbuf=mymalloc( SRAMIN, 100 ) ;                      //申請(qǐng)內(nèi)存
  if( tbuf==NULL )
    return ;
  //前三個(gè)IP保持和DHCP得到的IP一致
  lwipdev.remoteip[ 0 ] = lwipdev.ip[ 0 ] ;
  lwipdev.remoteip[ 1 ] = lwipdev.ip[ 1 ] ;
  lwipdev.remoteip[ 2 ] = lwipdev.ip[ 2 ] ;
  lwipdev.remoteip[ 3 ] = 113 ;
  sprintf( ( char* )tbuf, "Remote IP:%d.%d.%d.", lwipdev.remoteip[0], lwipdev.remoteip[1], lwipdev.remoteip[2] ) ;
  LCD_ShowString( 30, 150, tbuf ) ;                    //遠(yuǎn)端IP
  myfree( SRAMIN, tbuf ) ;
}
//關(guān)閉與服務(wù)器的連接
void tcp_client_connection_close( struct tcp_pcb *tpcb, struct tcp_client_struct *es )
{
  tcp_abort( tpcb ) ;                            //終止連接,刪除pcb控制塊
  tcp_arg( tpcb, NULL ) ;
  tcp_recv( tpcb, NULL ) ;
  tcp_sent( tpcb, NULL ) ;
  tcp_err( tpcb, NULL ) ;
  tcp_poll( tpcb, NULL, 0 );
  if( es )
    mem_free( es ) ;
  tcp_client_flag &= ~( 1<<5 ) ;                      //標(biāo)記連接斷開了
}
// tcp_recv函數(shù)的回調(diào)函數(shù)
u8 tcp_client_recvbuf[ TCP_CLIENT_RX_BUFSIZE ] ;                //接收數(shù)據(jù)緩沖區(qū)
err_t tcp_client_recv( void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err )
{
  u32 data_len=0 ;
  struct pbuf *q ;
  struct tcp_client_struct *es ;
  err_t ret_err ;
  LWIP_ASSERT( "arg != NULL", arg!=NULL ) ;
  es = ( struct tcp_client_struct* )arg ;
  //如果從服務(wù)器接收到空的數(shù)據(jù)幀就關(guān)閉連接
  if( p==NULL )
  {
    es->state = ES_TCPCLIENT_CLOSING ;                //需要關(guān)閉TCP連接了
     es->p = p ;
    ret_err = ERR_OK ;
  }
  //當(dāng)接收到一個(gè)非空的數(shù)據(jù)幀,但是err!=ERR_OK
  else if( err!=ERR_OK )
  { 
    if( p )
      pbuf_free( p ) ;                        //釋放接收pbuf
    ret_err = err ;
  }
  //當(dāng)處于連接狀態(tài)時(shí)
  else if( es->state==ES_TCPCLIENT_CONNECTED )
  {
    //當(dāng)處于連接狀態(tài)并且接收到的數(shù)據(jù)不為空時(shí)
    if( p!=NULL )
    {
      memset( tcp_client_recvbuf, 0, TCP_CLIENT_RX_BUFSIZE ) ;      //數(shù)據(jù)接收緩沖區(qū)清零
      //遍歷完整個(gè)pbuf鏈表
      for( q=p; q!=NULL; q=q->next )
      {
        if( q->len>( TCP_CLIENT_RX_BUFSIZE-data_len ) )
          memcpy( tcp_client_recvbuf+data_len, q->payload, TCP_CLIENT_RX_BUFSIZE-data_len ) ; 
        else
          memcpy( tcp_client_recvbuf+data_len, q->payload, q->len ) ;
        data_len += q->len ;
        //超出TCP客戶端接收數(shù)組,跳出
        if( data_len>TCP_CLIENT_RX_BUFSIZE )
          break ;
      }
      tcp_client_flag |= 1<<6 ;                    //標(biāo)記接收到數(shù)據(jù)了
       tcp_recved( tpcb,p->tot_len );                  //用于獲取接收數(shù)據(jù)
      pbuf_free( p ) ;                        //釋放內(nèi)存
      ret_err = ERR_OK ;
    }
  }
  //接收到數(shù)據(jù)但是連接已經(jīng)關(guān)閉
  else
  { 
    tcp_recved( tpcb, p->tot_len ) ;                    //用于獲取接收數(shù)據(jù)
    es->p = NULL ;
    pbuf_free( p ) ;                          //釋放內(nèi)存
    ret_err = ERR_OK ;
  }
  return ret_err ;
}
// tcp_err函數(shù)的回調(diào)函數(shù)
void tcp_client_error( void *arg, err_t err )
{


}
//發(fā)送數(shù)據(jù)
void tcp_client_senddata( struct tcp_pcb *tpcb, struct tcp_client_struct *es )
{
  struct pbuf *ptr ; 
   err_t wr_err = ERR_OK ;
  while( ( wr_err==ERR_OK )&&( es->p )&&( es->p->len<=tcp_sndbuf( tpcb ) ) )
  {
    ptr = es->p ;
    wr_err = tcp_write( tpcb, ptr->payload, ptr->len, 1 ) ;          //數(shù)據(jù)加入到發(fā)送緩沖隊(duì)列中
    if( wr_err==ERR_OK )
    {
      es->p = ptr->next ;                      //指向下一個(gè)pbuf
      //pbuf的ref加一
      if( es->p )
        pbuf_ref( es->p );
      pbuf_free( ptr ) ;                        //釋放ptr
    }
    else if( wr_err==ERR_MEM )
      es->p = ptr ;
    tcp_output( tpcb ) ;                        //發(fā)送緩沖隊(duì)列中的數(shù)據(jù)發(fā)送
  }
}
// tcp_sent的回調(diào)函數(shù)(從遠(yuǎn)端接收到ACK后發(fā)送數(shù)據(jù))
err_t tcp_client_sent( void *arg, struct tcp_pcb *tpcb, u16_t len )
{
  struct tcp_client_struct *es ;
  LWIP_UNUSED_ARG( len ) ;
  es = ( struct tcp_client_struct* )arg ;
  if( es->p )
    tcp_client_senddata( tpcb, es ) ;                    //發(fā)送數(shù)據(jù)
  return ERR_OK ;
}
// tcp_poll的回調(diào)函數(shù)
const u8 *tcp_client_sendbuf = "STM32F103 TCP Client send data\\r\\n" ;      //TCP服務(wù)器發(fā)送數(shù)據(jù)內(nèi)容
err_t tcp_client_poll( void *arg, struct tcp_pcb *tpcb )
{
  err_t ret_err ;
  struct tcp_client_struct *es ; 
  es = ( struct tcp_client_struct* )arg ;
  //連接處于空閑可以發(fā)送數(shù)據(jù)
  if( es!=NULL )
  {
    //判斷是否有數(shù)據(jù)要發(fā)送
    if( tcp_client_flag&( 1<<7 ) )
    {
      es->p = pbuf_alloc( PBUF_TRANSPORT, strlen( ( char* )tcp_client_sendbuf ), PBUF_POOL ) ; 
      pbuf_take( es->p, ( char* )tcp_client_sendbuf, strlen( ( char* )tcp_client_sendbuf ) ) ; 
      tcp_client_senddata( tpcb, es ) ;                  //將數(shù)據(jù)發(fā)送出去
      tcp_client_flag &= ~( 1<<7 ) ;                  //清除數(shù)據(jù)發(fā)送標(biāo)志
      //釋放內(nèi)存
      if( es->p )
        pbuf_free( es->p ) ;
    }
    else if( es->state==ES_TCPCLIENT_CLOSING )
       tcp_client_connection_close( tpcb, es ) ;              //關(guān)閉TCP連接
    ret_err = ERR_OK ;
  }
  else
  { 
    tcp_abort( tpcb ) ;                          //終止連接,刪除pcb控制塊
    ret_err = ERR_ABRT ;
  }
  return ret_err ;
}
//連接建立后調(diào)用回調(diào)函數(shù)
err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
  struct tcp_client_struct *es=NULL;  
  if(err==ERR_OK)   
  {
    es = ( struct tcp_client_struct* )mem_malloc( sizeof( struct tcp_client_struct ) ) ; //申請(qǐng)內(nèi)存
    //內(nèi)存申請(qǐng)成功
    if( es )
    {
       es->state = ES_TCPCLIENT_CONNECTED ;            //狀態(tài)為連接成功
      es->pcb = tpcb ;
      es->p = NULL ;
      tcp_arg( tpcb, es ) ;                      //更新tpcb的callback_arg
      tcp_recv( tpcb, tcp_client_recv ) ;                  //初始化tcp_recv回調(diào)功能
      tcp_err( tpcb, tcp_client_error ) ;                  //初始化tcp_err()回調(diào)函數(shù)
      tcp_sent( tpcb, tcp_client_sent ) ;                  //初始化tcp_sent回調(diào)功能
      tcp_poll( tpcb, tcp_client_poll, 1 ) ;                //初始化tcp_poll回調(diào)功能
       tcp_client_flag |= 1<<5 ;                    //標(biāo)記連接到服務(wù)器了
      err = ERR_OK ;
    }
    else
    {
      tcp_client_connection_close( tpcb, es ) ;              //關(guān)閉連接
      err = ERR_MEM ;                        //返回內(nèi)存分配錯(cuò)誤
    }
  }
  else
    tcp_client_connection_close( tpcb, 0 ) ;                //關(guān)閉連接
  return err ;
}
//客戶機(jī)測(cè)試
void tcp_client_test()
{
   struct tcp_pcb *tcppcb ;                        //定義一個(gè)TCP服務(wù)器控制塊
  struct ip_addr rmtipaddr ;                        //遠(yuǎn)端ip地址
  u8 *tbuf ;
  u8 res=0 ;    
  u8 t=0 ; 
  u8 connflag=0 ;                            //連接標(biāo)記
  tcp_client_set_remoteip() ;                        //先選擇IP
  tbuf = mymalloc( SRAMIN, 200 ) ;                    //申請(qǐng)內(nèi)存
  //內(nèi)存申請(qǐng)失敗了,直接退出
  if( tbuf==NULL )
    return ;
  sprintf( ( char* )tbuf, "Local IP:%d.%d.%d.%d", lwipdev.ip[0], lwipdev.ip[1], lwipdev.ip[2], lwipdev.ip[3] ) ;
  LCD_ShowString( 30, 130, tbuf ) ;                    //服務(wù)器IP
  sprintf( ( char* )tbuf, "Remote IP:%d.%d.%d.%d", lwipdev.remoteip[0], lwipdev.remoteip[1], lwipdev.remoteip[2], lwipdev.remoteip[3] ) ;
  LCD_ShowString( 30, 150, tbuf ) ;                    //遠(yuǎn)端IP
  sprintf( ( char* )tbuf, "Remote Port:%d", TCP_CLIENT_PORT ) ;          //客戶端端口號(hào)
  LCD_ShowString( 30, 170, tbuf ) ;
  LCD_ShowString( 30, 190, "STATUS:Disconnected" ) ;
  tcppcb = tcp_new() ;                          //創(chuàng)建一個(gè)新的pcb
  //創(chuàng)建成功
  if( tcppcb )
  {
  IP4_ADDR( &rmtipaddr, lwipdev.remoteip[0], lwipdev.remoteip[1], lwipdev.remoteip[2], lwipdev.remoteip[3] ) ;
    tcp_connect( tcppcb, &rmtipaddr, TCP_CLIENT_PORT, tcp_client_connected ) ; 
   }
  else
    res = 1 ;
  while( res==0 )
  {
    //是否收到數(shù)據(jù)
    if( tcp_client_flag&1<<6 )
    {
      LCD_ShowString( 30, 230, tcp_client_recvbuf ) ;            //顯示接收到的數(shù)據(jù)
      tcp_client_flag |= 1<<7 ;                    //標(biāo)記要發(fā)送數(shù)據(jù)
      tcp_client_flag &= ~( 1<<6 ) ;                  //標(biāo)記數(shù)據(jù)已經(jīng)被處理了
    }
    //是否連接上
    if( tcp_client_flag&1<<5 )
    {
      if( connflag==0 )
      { 
        LCD_ShowString( 30, 190, "STATUS:Connected   " ) ;
        LCD_ShowString( 30, 210, "Receive Data:" ) ;
        connflag = 1 ;                        //標(biāo)記連接了
      }
    }
    else if( connflag )
    {
       LCD_ShowString( 30, 190, "STATUS:Disconnected" ) ;
      connflag = 0 ;                          //標(biāo)記連接斷開了
    } 
    lwip_periodic_handle() ;
    lwip_pkt_handle() ;
    delay_ms( 2 ) ;
    t ++ ;
    if( t==200 )
    {
      //未連接上,則嘗試重連
      if( ( connflag==0 )&&( ( tcp_client_flag&1<<5 )==0 ) )
      { 
        tcp_client_connection_close( tcppcb, 0 ) ;            //關(guān)閉連接
        tcppcb = tcp_new() ;                    //創(chuàng)建一個(gè)新的pcb
        //創(chuàng)建成功
        if( tcppcb )
          tcp_connect( tcppcb, &rmtipaddr, TCP_CLIENT_PORT, tcp_client_connected ) ; 
      }
      t = 0 ;
    }    
  }
  tcp_client_connection_close( tcppcb, 0 ) ;                  //關(guān)閉TCP Client連接
  myfree( SRAMIN, tbuf ) ;
}

26.2.2 tcp_client.h代碼編寫

#ifndef _TCP_CLIENT_H_
#define _TCP_CLIENT_H_
#include "sys.h"
#include "lwip/tcp.h"
#include "lwip/pbuf.h"
#define TCP_CLIENT_RX_BUFSIZE  1500            //最大接收數(shù)據(jù)長(zhǎng)度
#define TCP_CLIENT_TX_BUFSIZE  200              //最大發(fā)送數(shù)據(jù)長(zhǎng)度
#define LWIP_SEND_DATA      0x80            //有數(shù)據(jù)發(fā)送
#define  TCP_CLIENT_PORT    8087            //遠(yuǎn)端端口
//tcp服務(wù)器連接狀態(tài)
enum tcp_client_states
{
  ES_TCPCLIENT_NONE = 0,    //沒有連接
  ES_TCPCLIENT_CONNECTED,  //連接到服務(wù)器了 
  ES_TCPCLIENT_CLOSING,    //關(guān)閉連接
};
//LWIP回調(diào)函數(shù)使用的結(jié)構(gòu)體
struct tcp_client_struct
{
  u8 state;            //當(dāng)前連接狀
  struct tcp_pcb *pcb;      //指向當(dāng)前的pcb
  struct pbuf *p;        //指向接收/或傳輸?shù)膒buf
};  
void tcp_client_test( void ) ;                    //TCP Client測(cè)試函數(shù)
#endif

26.2.3 主函數(shù)代碼編寫

#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "tim.h"
#include "lcd.h"
#include "malloc.h"
#include "dm9000.h"
#include "lwip/netif.h"
#include "comm.h"
#include "lwipopts.h"
#include "tcp_client.h"
int main()
{
  u8 buf[ 30 ];
   STM32_Clock_Init( 9 ) ;                        //系統(tǒng)時(shí)鐘設(shè)置
  SysTick_Init( 72 ) ;                          //延時(shí)初始化
  USART1_Init( 72, 115200 ) ;                      //串口初始化為115200
  LCD_Init() ;                            //初始化LCD
  TIM3_Init( 1000, 719 ) ;                        //定時(shí)器3頻率為100hz
  my_mem_init( SRAMIN ) ;                      //初始化內(nèi)部?jī)?nèi)存池
  while( lwip_comm_init() ) ;                      //lwip初始化
  //等待DHCP獲取成功/超時(shí)溢出
  while( ( lwipdev.dhcpstatus!=2 )&&( lwipdev.dhcpstatus!=0xFF ) )
  {
    lwip_periodic_handle() ;                    //LWIP內(nèi)核需要定時(shí)處理的函數(shù)
    lwip_pkt_handle() ;
  }
  POINT_COLOR=RED;
  LCD_ShowString( 30, 110, "LWIP Init Successed" ) ;
  //打印動(dòng)態(tài)IP地址
  if( lwipdev.dhcpstatus==2 )
    sprintf( ( char* )buf, "DHCP IP:%d.%d.%d.%d", lwipdev.ip[0], lwipdev.ip[1], lwipdev.ip[2], lwipdev.ip[3] ) ;
  //打印靜態(tài)IP地址
  else
    sprintf( ( char* )buf, "Static IP:%d.%d.%d.%d", lwipdev.ip[0], lwipdev.ip[1], lwipdev.ip[2], lwipdev.ip[3] ) ;
  LCD_ShowString( 30, 130, buf ) ; 
  //得到網(wǎng)速
  if( ( DM9000_Get_SpeedAndDuplex()&0x02 )==0x02 )
    LCD_ShowString( 30, 150, "Ethernet Speed:10M" ) ;
  else
    LCD_ShowString( 30, 150, "Ethernet Speed:100M" ) ;
   while( 1 )
  {
    tcp_client_test() ;
    lwip_periodic_handle() ;
    lwip_pkt_handle() ;
    delay_ms( 2 ) ;
  }
}

26.3 實(shí)驗(yàn)結(jié)果

圖片

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

    關(guān)注

    8

    文章

    1324

    瀏覽量

    78756
  • MSS
    MSS
    +關(guān)注

    關(guān)注

    0

    文章

    5

    瀏覽量

    6700
  • 傳輸層協(xié)議
    +關(guān)注

    關(guān)注

    0

    文章

    6

    瀏覽量

    1238
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    LABVIEW實(shí)現(xiàn)網(wǎng)絡(luò)通信的方法

    網(wǎng)絡(luò)通信,可以使用的通信協(xié)議類型包括TCP/IP協(xié)議、UDP、串口通信協(xié)議、無線網(wǎng)絡(luò)協(xié)議等;(2)使用基于
    發(fā)表于 12-12 18:02

    四種在LabVIEW中實(shí)現(xiàn)網(wǎng)絡(luò)通信的方法

    方便的實(shí)現(xiàn)數(shù)據(jù)的共享。用戶無需了解任何的底層復(fù)雜的網(wǎng)絡(luò)通信,就能輕松地實(shí)現(xiàn)數(shù)據(jù)交換。用戶建立和使用共享變量就如同操作全局變量一樣方便?! ?.2 利用共享變量通信實(shí)例  以下通過C/S(客戶端/服務(wù)器
    發(fā)表于 02-04 15:32

    labview TCP客戶端

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

    【NanoPi NEO試用體驗(yàn)】TCP通信客戶端程序

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

    android的Tcp網(wǎng)絡(luò)通信

    在所有的通信中,網(wǎng)絡(luò)通信是用到的比較多的一種,這一節(jié)我們主要是在廣州微嵌安卓工業(yè)平板上學(xué)習(xí)是如何進(jìn)行Tcp通信的。Tcp
    發(fā)表于 12-05 10:49

    基于LABVIEW實(shí)現(xiàn)網(wǎng)絡(luò)通信的方法

    任何的底層復(fù)雜的網(wǎng)絡(luò)通信,就能輕松地實(shí)現(xiàn)數(shù)據(jù)交換。用戶建立和使用共享變量就如同操作全局變量一樣方便。4.2 利用共享變量通信實(shí)例  以下通過C/S(客戶端/服務(wù)器)通信模式實(shí)現(xiàn)數(shù)據(jù)的傳
    發(fā)表于 04-28 10:04

    請(qǐng)問在做網(wǎng)絡(luò)通信試驗(yàn)時(shí),PC一般是客戶端還是服務(wù)器?

    原子哥以及論壇里面的各位大神,請(qǐng)問在做網(wǎng)絡(luò)通信試驗(yàn)時(shí),PC一般是客戶端還是服務(wù)器?單片機(jī)這邊應(yīng)該是客戶端還是服務(wù)器?
    發(fā)表于 06-27 02:12

    為什么網(wǎng)絡(luò)通信實(shí)驗(yàn)TCP客戶端模式時(shí)連接不上?

    戰(zhàn)艦V3上的實(shí)驗(yàn)50 網(wǎng)絡(luò)通信實(shí)驗(yàn),當(dāng)用TCP服務(wù)器模式時(shí),通信正常,用TCP
    發(fā)表于 08-16 04:35

    為什么網(wǎng)絡(luò)通信實(shí)驗(yàn)網(wǎng)絡(luò)助手上接受到的先是456個(gè)字節(jié)?

    網(wǎng)絡(luò)通信實(shí)驗(yàn)里將ARMF407配置成sever,通過電腦上網(wǎng)絡(luò)助手接受ARM發(fā)送到數(shù)據(jù),將tcp_sever_sendbuf[1000]改成一個(gè)1000的大數(shù)組并賦值,但是在網(wǎng)絡(luò)助手
    發(fā)表于 09-02 02:54

    STM32F103上網(wǎng)絡(luò)通信實(shí)驗(yàn)中服務(wù)器與客戶端連接但不能進(jìn)行數(shù)據(jù)交換該怎么辦?

    我在應(yīng)用原子哥的103板子的網(wǎng)絡(luò)通信實(shí)驗(yàn)時(shí),發(fā)現(xiàn)了一個(gè)小問題,就是在服務(wù)器模式下,板子可以與很多的客戶端建立連接,但是在進(jìn)行數(shù)據(jù)交換時(shí),卻只能和第一個(gè)連上的客戶端進(jìn)行數(shù)據(jù)交換,只有在于這個(gè)客戶
    發(fā)表于 10-15 04:37

    基于原子STM32F4的攝像頭與網(wǎng)絡(luò)通信實(shí)驗(yàn)

    網(wǎng)絡(luò)通信C/S方式將STM32攝像頭拍取的照片傳輸?shù)诫娔X在PC開發(fā)可視化界面接受攝像頭數(shù)據(jù)并更新顯示2.實(shí)施步驟:1.參考STM32原子攝像頭實(shí)驗(yàn)
    發(fā)表于 08-03 06:04

    stm32f107vc lwip tcp客戶端

    模擬的服務(wù)器,實(shí)現(xiàn)簡(jiǎn)單的數(shù)據(jù)收發(fā),通過上位機(jī)控制板子的LED燈一 打開工程《科星F107開發(fā)板網(wǎng)絡(luò)應(yīng)用篇TCP客戶端》打開M
    發(fā)表于 08-06 09:17

    基于TCP/IP的網(wǎng)絡(luò)通信應(yīng)用程序分享

    基于TCP/IP的網(wǎng)絡(luò)通信應(yīng)用程序(TCP-Server)上一篇文章講述了在i.MX6UL開發(fā)板中,以客戶端的角色,使用TCP/IP協(xié)議進(jìn)行
    發(fā)表于 12-23 08:12

    網(wǎng)絡(luò)調(diào)試和串口調(diào)試集合UDP TCP客戶端TCP服務(wù)器應(yīng)用程序免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是網(wǎng)絡(luò)調(diào)試和串口調(diào)試集合UDP TCP客戶端TCP服務(wù)器應(yīng)用程序免費(fèi)下載。
    發(fā)表于 08-30 08:00 ?16次下載
    <b class='flag-5'>網(wǎng)絡(luò)</b>調(diào)試和串口調(diào)試集合UDP <b class='flag-5'>TCP</b><b class='flag-5'>客戶端</b>和<b class='flag-5'>TCP</b>服務(wù)器<b class='flag-5'>端</b>應(yīng)用程序免費(fèi)下載

    網(wǎng)絡(luò)通信的特點(diǎn)

    網(wǎng)絡(luò)通信可以分為兩大類:客戶端準(zhǔn)客戶端(C/S)和Peer-To-Peer(P2P)網(wǎng)絡(luò)通信。其中,客戶端/服務(wù)器式
    發(fā)表于 05-08 15:12 ?2057次閱讀