基于Lwip的TCP框架

Hi , 今天还是32的。开源一个基于lwip-raw tcp的框架。
主要也是解决下列这些问题并且减少一些开发者对lwip的研究时间,比如说:

  1. 盲目使用tcp_connect函数会产生多连接问题
  2. 若连接的目标不存在(对方无法返回RST)
  3. 若连接的目标存在且禁止连接时(返回RST)

My_TcpManager.c

/********************************************************************************************************
/                                                Doon OS-I
/                                          The Doon-app Wireled manager
/
/
/                         (c) Copyright 2019-2023; Micrium, Inc.; ShenZhen, FL
/                    All rights reserved.  You may obtain a copy of the License at:.
/
/                                     https://me.youkuaiyun.com/weixin_40952498
/
/ File      : My_NetManager.c
/ Version   : V0.00.01
/ By        : Doon
/ e-mail : 1176964408@qq.com
/ Date  : 2019-July 2 Tuesday
/
/ For       : STM32F407VET6
/ Mode      : Thread mode
/ Toolchain : Source Insight 4.0
********************************************************************************************************/
#include "project.h"
/* <! public function > */
err_t VI_CMode_Callback(void *arg, struct tcp_pcb *newpcb, err_t err);
err_t VI_SMode_Callback(void *arg, struct tcp_pcb *newpcb, err_t err);
err_t VI_CSMode_Recv(void *arg,struct tcp_pcb *tpcb,struct pbuf *p,err_t err);
struct My_NetList * VI_SMode_insert(struct My_NetList *head,struct My_NetList add);
int VI_SMode_deleted(struct My_NetList *head,struct tcp_pcb *socket);
err_t Test_Parse(struct My_NetList *node,char *buffer,unsigned short length);
void VI_CMode_IPParse(const char *name, struct ip_addr *ipaddr, void *arg);
int VI_Net_Suspend(char *name);
int VI_Net_Resume(char *name);

/* pbuf recv parse function */
extern err_t Telnet_Parse(struct My_NetList *node,char *buffer,unsigned short length);
//extern err_t Upper_Parse(struct My_NetList *node,char *buffer,unsigned short length);
//extern err_t Cloud_Parse(struct My_NetList *node,char *buffer,unsigned short length);
//extern err_t Approve_Parse(struct My_NetList *node,char *buffer,unsigned short length);
//extern err_t My_Cloud_Verify( struct My_NetList *node , char *buffer , unsigned short len );
//extern err_t  Upper_parse( struct My_NetList *node,char *buffer,unsigned short length );
//extern err_t  ReegaBuss_parse( struct My_NetList *node,char *buffer,unsigned short length );
/* connect failed handler */
//extern err_t Cloud_cfhandler(struct My_NetList *node);

/*
 * My Net Manager.
*/
My_NetList_Def My_NetList[]=
{
// {
//  .name = "Approve", .cs_mode = CS_MODE_CLIENT, .cs_rmport = 10106, .dns = "My-home.com",
//  .socket = NULL, .buffer_length = 200, .suspend = false, .Heatbeat_Setting = HEATBEAT_DEFAULT,
//  .keepalive = false, .Parse = Approve_Parse, .cf_handler = NULL},
// {
//  .name = "Cloud", .cs_mode = CS_MODE_CLIENT, .cs_rmport = 99999, .dns = /*NULL ,*/"47.94.166.7",
//  .socket = NULL, .buffer_length = 100, .suspend = false, .Heatbeat_Setting = HEATBEAT_DEFAULT,
//  .keepalive = false, .Parse = Cloud_Parse , .cf_handler = NULL/*Cloud_cfhandler*/},
// {
//  .name = "Upper", .cs_mode = CS_MODE_SERVER, .cs_loport = 48438, .dns = NULL,
//  .socket = NULL , .buffer_length = 2048, .suspend = false , .Heatbeat_Setting = HEATBEAT_DEFAULT,
//  .keepalive = false, .Parse = Upper_parse, .cf_handler = NULL},
 {
  .name = "Telnet", .cs_mode = CS_MODE_SERVER, .cs_loport = 23, .dns = NULL,
  .socket = NULL, .buffer_length = 50, .suspend = false , .Heatbeat_Setting = HEATBEAT_NOCOUNT,
  .keepalive = true, .Parse = Telnet_Parse, .cf_handler = NULL},
// {
//  .name = "ThirdP", .cs_mode = CS_MODE_SERVER, .cs_loport = 48439, .dns = NULL,
//  .socket = NULL, .buffer_length = 2048, .suspend = false , .Heatbeat_Setting = HEATBEAT_DEFAULT ,
//  .keepalive = false, .Parse = Cloud_Parse, .cf_handler = NULL},
// {
//  .name = "Redir", .cs_mode = CS_MODE_CLIENT, .cs_rmport = 9100, .dns = "114.55.171.67",
//  .socket = NULL, .buffer_length = 512, .suspend = true , .Heatbeat_Setting = HEATBEAT_DEFAULT,
//  .keepalive = false, .Parse = ReegaRes_parse , .cf_handler = NULL},
// {
//  .name = "BOSCH", .cs_mode = CS_MODE_CLIENT, .cs_rmport = 0, .dns = NULL,
//  .socket = NULL, .buffer_length = 2048, .suspend = true , .Heatbeat_Setting = 140,
//  .keepalive = false, .Parse = ReegaBuss_parse , .cf_handler = NULL}, 
};

static const char * const g_stEthstatus[] = {"CLOSED","LISTEN","SYN_SENT","SYN_RCVD","ESTABLISHED","FIN_WAIT_1","FIN_WAIT_2","CLOSE_WAIT","CLOSING","LAST_ACK","TIME_WAIT"};
/*
* Description : The error of C/S mode
*/
void VI_Neterr(void *arg,err_t err)
{
 struct My_NetList *Net_node;
 //MyOS_Node_Def item;
 if(arg == NULL) return;
 else Net_node = (struct My_NetList *)arg;
 
 switch(err)
 {
  case ERR_ABRT:
   /* The package resend 6times. the pcb have free */
   /* 1.st set socket to null */
   if(Net_node->cs_mode == CS_MODE_CLIENT)
   {
    /* info the core that some one is break. */
    //item.Event_Type = OS_EVENT_NET_CONNECTED;
    //item.data.Net_info.cs_mode = Net_node->cs_mode;
    //item.data.Net_info.io_select = OS_CONN_CLOSE;
    //sprintf(item.data.Net_info.name,"%s",Net_node->name);
    //if(Net_node->cs_mode == CS_MODE_CLIENT)  item.data.Net_info.port = Net_node->cs_rmport; // client mode
    //else          item.data.Net_info.port = Net_node->cs_loport; // thirdp mode
    //item.data.Net_info.socket = Net_node->socket;
    //Enqueue(item);
    
    /* handle the inal touches. */
    if(Net_node->connect_state != ESTABLISHED && Net_node->cf_handler != NULL)
    {
     Net_node->cf_handler(Net_node);
    }
    Net_node->socket->callback_arg = NULL;
    Net_node->socket->recv = NULL;
    Net_node->socket->sent = NULL;
    Net_node->socket->errf = NULL;
    Net_node->socket->poll = NULL;
    Net_node->socket->pollinterval = 0;
    Net_node->socket = NULL;
    Net_node->connect_state = CLOSED;
   }
   else if(Net_node->cs_mode == CS_MODE_THIRDP)
   {
    unsigned char length,i;
    length = sizeof(My_NetList)/sizeof(My_NetList[0]);
    for(i = 0 ; i < length ; i++)
    {
     if(Net_node->cs_rmport == My_NetList[i].cs_loport)
     {
      VI_SMode_deleted(&My_NetList[i],Net_node->socket);
     }
    }
   }
   break;
  case ERR_RST:
  case ERR_CLSD:
   /* The package was broken. the pcb have free */
   /* 1.st set socket to null */
   if(Net_node->cs_mode == CS_MODE_CLIENT)
   {
    /* info the core that some one is break. */
    //item.Event_Type = OS_EVENT_NET_CONNECTED;
    //item.data.Net_info.cs_mode = Net_node->cs_mode;
    //item.data.Net_info.io_select = OS_CONN_CLOSE;
    //sprintf(item.data.Net_info.name,"%s",Net_node->name);
    //if(Net_node->cs_mode == CS_MODE_CLIENT)  item.data.Net_info.port = Net_node->cs_rmport; // client mode
    //else           item.data.Net_info.port = Net_node->cs_loport; // thirdp mode
    //item.data.Net_info.socket = Net_node->socket;
    //Enqueue(item);
    
    /* handle the inal touches. */
    if(Net_node->connect_state != ESTABLISHED && Net_node->cf_handler != NULL)
    {
     Net_node->cf_handler(Net_node);
    }
    Net_node->socket->callback_arg = NULL;
    Net_node->socket->recv = NULL;
    Net_node->socket->sent = NULL;
    Net_node->socket->errf = NULL;
    Net_node->socket->poll = NULL;
    Net_node->socket->pollinterval = 0;
    Net_node->socket = NULL;
    Net_node->connect_state = CLOSED;
   }
   else if(Net_node->cs_mode == CS_MODE_THIRDP)
   {
    unsigned char length,i;
    length = sizeof(My_NetList)/sizeof(My_NetList[0]);
    for(i = 0 ; i < length ; i++)
    {
     if(Net_node->cs_rmport == My_NetList[i].cs_loport)
     {
      VI_SMode_deleted(&My_NetList[i],Net_node->socket);
     }
    }
   }
   /* waitting for reconnect or  */
   break;
  default:
   Dbg("Unknow err:%d",err);
   break;
 }
}

/*
 *@ The NetManager init . 
 Server mode :  bind , listen and accept socket.
 Client mode :  connect to remote server.
*/
void VI_NetInit(void)
{
 unsigned char i,length;
// err_t err;
// ip_addr_t addr;
// unsigned char l_byTimecount = 0;
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 
 // parse dns's ip first
 for(i = 0 ; i < length ; i++)
 {
//  if(My_NetList[i].cs_mode == CS_MODE_CLIENT)
//  {
//   if(My_NetList[i].dns != NULL)
//   {
//    // find it . so we try to parse the ip from dns
//    l_byTimecount++;
//    err = dns_gethostbyname(My_NetList[i].dns,&addr,VI_CMode_IPParse,&My_NetList[i]);
//    if(err == ERR_OK)
//    {
//     // host name already in octet notation.
//     // the callback function will not call
//     My_NetList[i].cs_remoteip[3] = addr.addr >> 24; My_NetList[i].cs_remoteip[2] = addr.addr >> 16;
//     My_NetList[i].cs_remoteip[1] = addr.addr >>  8; My_NetList[i].cs_remoteip[0] = addr.addr;
//    }
//   }
//  }
//  // In the head of init . clear user data
  My_NetList[i].connect_state = CLOSED;
  memset(My_NetList[i].usrdata.by,0,USR_DATA_LENGTH);
 }
 
 // Here we should wait for ETH Interrupt.
// delay_ms(500 * l_byTimecount);
 
 for(i = 0 ; i < length ; i++)
 {
  switch(My_NetList[i].cs_mode)
  {
   case CS_MODE_CLIENT:
   {
//    if(My_NetList[i].suspend == false)
//    {
//     struct ip_addr rmtipaddr;
//     IP4_ADDR(&rmtipaddr,My_NetList[i].cs_remoteip[0],My_NetList[i].cs_remoteip[1],My_NetList[i].cs_remoteip[2],My_NetList[i].cs_remoteip[3]);
//     My_NetList[i].socket = tcp_new();
//     /* set arg */
//     tcp_arg(My_NetList[i].socket,&My_NetList[i]);
//     /* set err callback function */
//     tcp_err(My_NetList[i].socket,VI_Neterr);
//     /* Try to connect */
//     tcp_connect(My_NetList[i].socket,&rmtipaddr,My_NetList[i].cs_rmport,VI_CMode_Callback);
//     My_NetList[i].connect_state = SYN_SENT;
//    }
   }break;
   case CS_MODE_SERVER:
   {
    if(My_NetList[i].suspend == false)
    {
     My_NetList[i].socket = tcp_new();
     if(My_NetList[i].socket)
     {
      tcp_bind(My_NetList[i].socket,IP_ADDR_ANY,My_NetList[i].cs_loport);
      My_NetList[i].socket = tcp_listen(My_NetList[i].socket);
      tcp_accept(My_NetList[i].socket,VI_SMode_Callback);
      tcp_arg(My_NetList[i].socket,&My_NetList[i]);
      My_NetList[i].socket->so_options |= (My_NetList[i].keepalive == true ? SOF_KEEPALIVE : 0x00U);
      /* fine. each server mode should be a link head */
      My_NetList[i].col_next = &My_NetList[i];
      My_NetList[i].col_pre  = &My_NetList[i];
     }
    }
   }break;
   default:
   {
    Dbg("Unknow cs mode : %d",My_NetList[i].cs_mode);
   }break;
  }
 }
}

/*
 *@ The NetManager release . 
 Server mode :  shutdown this socket.
 Client mode :  susped and disconnect this socket .
*/
void VI_NetRelease(void)
{
 unsigned char length,i;
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 
 for( i = 0 ; i < length ; i++ )
 {
  switch(My_NetList[i].cs_mode)
  {
   case CS_MODE_CLIENT:
   {
    /* Suspend this socket and disconnect from remote */
//    VI_Net_Suspend(My_NetList[i].name);
    VI_Net_shutdown(My_NetList[i].name);
   }break;
   case CS_MODE_SERVER:
   {
    /* disconnect all socket on this port */
    VI_Net_shutdown(My_NetList[i].name);
   }break;
   default:
    Dbg("Unknow cs mode : %d",My_NetList[i].cs_mode);
    break;
  }
 }
}

/*
 *@ Description -> check if socket have broken or 
*/
void VI_NetReconnectCheck( /*OS_State *MyOS_State*/ void )
{
 unsigned char i,length;
 struct My_NetList *p = NULL;
 
 //if( MyOS_State->DHCP_Enable == false || ( MyOS_State->DHCP_Enable == true && MyOS_State->Router_State == true ) )
 {
  length = sizeof(My_NetList)/sizeof(My_NetList[0]);
  for(i = 0 ; i < length ; i++)
  {
   /* check which socket should be reconnect */
   if(My_NetList[i].connect_state == CLOSED &&\
    My_NetList[i].cs_mode == CS_MODE_CLIENT &&\
    My_NetList[i].socket == NULL &&\
    My_NetList[i].suspend == false)
   {
    if(My_NetList[i].dns == NULL)
    {
     struct ip_addr rmtipaddr;
     IP4_ADDR(&rmtipaddr,My_NetList[i].cs_remoteip[0],My_NetList[i].cs_remoteip[1],My_NetList[i].cs_remoteip[2],My_NetList[i].cs_remoteip[3]);
     /* reconnect do it */
     My_NetList[i].socket = tcp_new();
     /* set arg */
     tcp_arg(My_NetList[i].socket,&My_NetList[i]);
     /* set err callback function */
     tcp_err(My_NetList[i].socket,VI_Neterr);
     /* try to reconnect */
     tcp_connect(My_NetList[i].socket,&rmtipaddr,My_NetList[i].cs_rmport,VI_CMode_Callback);
     My_NetList[i].connect_state = SYN_SENT;
     My_NetList[i].socket->so_options |= (My_NetList[i].keepalive == true ? SOF_KEEPALIVE : 0x00U);
    }
    else
    {
     ip_addr_t addr;
     struct ip_addr rmtipaddr;
     err_t err;
     
     err = dns_gethostbyname(My_NetList[i].dns,&addr,VI_CMode_IPParse,&My_NetList[i]);
     if(err == ERR_OK)
     {
      // host name already in octet notation.
      // the callback function will not call
      My_NetList[i].cs_remoteip[3] = addr.addr >> 24; My_NetList[i].cs_remoteip[2] = addr.addr >> 16;
      My_NetList[i].cs_remoteip[1] = addr.addr >>  8; My_NetList[i].cs_remoteip[0] = addr.addr;
      
      IP4_ADDR(&rmtipaddr,My_NetList[i].cs_remoteip[0],My_NetList[i].cs_remoteip[1],My_NetList[i].cs_remoteip[2],My_NetList[i].cs_remoteip[3]);
      /* reconnect do it */
      My_NetList[i].socket = tcp_new();
      /* set arg */
      tcp_arg(My_NetList[i].socket,&My_NetList[i]);
      /* set err callback function */
      tcp_err(My_NetList[i].socket,VI_Neterr);
      /* try to reconnect */
      tcp_connect(My_NetList[i].socket,&rmtipaddr,My_NetList[i].cs_rmport,VI_CMode_Callback);
      My_NetList[i].connect_state = SYN_SENT;
     }
    }
   }
   
   /* count the heart beat */
   switch(My_NetList[i].cs_mode)
   {
    case CS_MODE_CLIENT:
    {
     if(My_NetList[i].connect_state == ESTABLISHED)
     {
      if(My_NetList[i].Heatbeat == 0)
      {
       /* heart beat time use up */
       VI_Net_shutdown(My_NetList[i].name);
      }
      
      if(My_NetList[i].Heatbeat != 0xffff)  My_NetList[i].Heatbeat--;
     }
    }break;
    case CS_MODE_SERVER:
    {
     for(p = My_NetList[i].col_next ; p != &My_NetList[i] ; p = p->col_next)
     {
      if(p->connect_state == ESTABLISHED)
      {
       if(p->Heatbeat == 0)
       {
        VI_Net_shutdown(p->name);
       }
       
       if(p->Heatbeat != 0xffff) p->Heatbeat--;
      }
     }
    }break;
   }
  }
 }
}

/*
 * Get the node
*/
struct My_NetList *VI_Net_Getnode(char *name)
{
 unsigned char i,length;
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 
 for(i = 0 ; i < length ; i++)
 {
  if(strcmp(My_NetList[i].name,name) == 0)
  {
   return &My_NetList[i];
  }
 }
 return NULL;
}

/*
 * Suspend this socket
*/
int VI_Net_Suspend(char *name)
{
 unsigned char i,length;
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 
 for(i = 0 ; i < length ; i++)
 {
  if(strcmp(My_NetList[i].name,name) == 0)
  {
   My_NetList[i].suspend = true;
   return 0;
  }
 }
 return -1;
}

/*
 * Resume this socket
*/
int VI_Net_Resume(char *name)
{
 unsigned char i,length;
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 
 for(i = 0 ; i < length ; i++)
 {
  if(strcmp(My_NetList[i].name,name) == 0)
  {
   My_NetList[i].suspend = false;
   return 0;
  }
 }
 return -1;
}

/*
 * Heatbeat reset
*/
int VI_Net_HBReset(char *name)
{
 unsigned char i,length;
 struct My_NetList *p = NULL;
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 
 for(i = 0 ; i < length ; i++)
 {
  switch(My_NetList[i].cs_mode)
  {
   case CS_MODE_CLIENT:
    if(strcmp(My_NetList[i].name,name) == 0)
    {
     My_NetList[i].Heatbeat = My_NetList[i].Heatbeat_Setting;
     return 0;
    }
    break;
   case CS_MODE_SERVER:
    for(p = My_NetList[i].col_next ; p != &My_NetList[i] ; p = p->col_next)
    {
     if(strcmp(p->name,name) == 0)
     {
      p->Heatbeat = p->Heatbeat_Setting;
      return 0;
     }
    }
    break;
   default:
    break;
  }
 }
 return -1;
}

/*
 * shoutdown this socket
*/
int VI_Net_shutdown(char *name)
{
 unsigned char i,length;
 struct My_NetList *p = NULL;
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 
 for(i = 0 ; i < length ; i++)
 {
  switch(My_NetList[i].cs_mode)
  {
   case CS_MODE_CLIENT:
   {
    if(strcmp(My_NetList[i].name,name) == 0)
    {
     My_NetList[i].socket->callback_arg = NULL;
     My_NetList[i].socket->recv = NULL;
     My_NetList[i].socket->sent = NULL;
     My_NetList[i].socket->errf = NULL;
     My_NetList[i].socket->poll = NULL;
     My_NetList[i].socket->pollinterval = 0;
     tcp_close(My_NetList[i].socket);
     My_NetList[i].socket = NULL;
     My_NetList[i].connect_state = CLOSED;
     return 0;
    }
   }break;
   
   case CS_MODE_SERVER:
   {
    if(strcmp(My_NetList[i].name,name) == 0)
    {
     /* maybe we should close all connection mount this port */
     for( p = My_NetList[i].col_next ; p != &My_NetList[i] ; p = p->col_next )
     {
      p->socket->callback_arg = NULL;
      p->socket->recv = NULL;
      p->socket->sent = NULL;
      p->socket->errf = NULL;
      p->socket->poll = NULL;
      p->socket->pollinterval = 0;
      tcp_close( p->socket );
      VI_SMode_deleted( &My_NetList[i] , p->socket );
      p->socket = NULL;
     }
     return 0;
    }
    else
    {
     /* find children */
     for( p = My_NetList[i].col_next ; p != &My_NetList[i] ; p = p->col_next )
     {
      if( strcmp( p->name , name ) == 0 )
      {
       p->socket->callback_arg = NULL;
       p->socket->recv = NULL;
       p->socket->sent = NULL;
       p->socket->errf = NULL;
       p->socket->poll = NULL;
       p->socket->pollinterval = 0;
       tcp_close( p->socket );
       VI_SMode_deleted( &My_NetList[i] , p->socket );
       p->socket = NULL;
       return 0;
      }
     }
    }
   }break;
   
   default:
    break;
  }
 }
 return -1;
}

/*
* Description : The callback function of client mode
*/
err_t VI_CMode_Callback(void *arg, struct tcp_pcb *newpcb, err_t err)
{
 MyOS_Node_Def item;
 // The Client mode established
 struct My_NetList *Net_node;
 Net_node = (struct My_NetList *)arg;
 Net_node->connect_state = ESTABLISHED;
 Net_node->Heatbeat = Net_node->Heatbeat_Setting;
 // Here we should init some callback function
 newpcb->recv = VI_CSMode_Recv;  // set recv_cb function to a new tcppcb
 
 /* send a info to core */
 item.Event_Type = OS_EVENT_NET_CONNECTED;
 item.data.Net_info.cs_mode = CS_MODE_CLIENT;
 item.data.Net_info.io_select = OS_CONN_CONNECTED;
 sprintf(item.data.Net_info.name,"%s",Net_node->name);
 item.data.Net_info.port = Net_node->cs_rmport;
 item.data.Net_info.socket = newpcb;
 Enqueue(item);
 
 return ERR_OK;
}

/*
* Description : The callback function of server mode
*/
err_t VI_SMode_Callback(void *arg, struct tcp_pcb *newpcb, err_t err)
{
 // The Server mode established.
 struct My_NetList *Net_head;
 struct My_NetList Net_node;
 //MyOS_Node_Def item;
 unsigned char l_byTemp_IP[4];
 
 if(arg != NULL)
 {
  /* a new connect link to local server */
  Net_head = (struct My_NetList *)arg;
  l_byTemp_IP[3] = newpcb->remote_ip.addr>>24;
  l_byTemp_IP[2] = newpcb->remote_ip.addr>>16;
  l_byTemp_IP[1] = newpcb->remote_ip.addr>>8;
  l_byTemp_IP[0] = newpcb->remote_ip.addr>>0;
  sprintf(Net_node.name,"%d.%d.%d.%d-%d",l_byTemp_IP[0],l_byTemp_IP[1],l_byTemp_IP[2],l_byTemp_IP[3],newpcb->remote_port);
  Net_node.cs_mode = CS_MODE_THIRDP;
  Net_node.cs_loport = newpcb->remote_port;
  Net_node.cs_rmport = Net_head->cs_loport;
  Net_node.connect_state = ESTABLISHED;
  Net_node.socket = newpcb;
  Net_node.socket->recv = VI_CSMode_Recv;
  Net_node.socket->errf = VI_Neterr;
  Net_node.buffer_length = Net_head->buffer_length;
  Net_node.Parse = Net_head->Parse;
  Net_node.Heatbeat = Net_head->Heatbeat_Setting;
  Net_node.Heatbeat_Setting = Net_head->Heatbeat_Setting;
  memset(Net_node.usrdata.by,0,USR_DATA_LENGTH);
  /* All init finish. set argument to platform */
  Net_node.socket->callback_arg = VI_SMode_insert(Net_head,Net_node);
  if(Net_node.socket->callback_arg == NULL)
  {
   return ERR_MEM;
  }
  
  /* send a info to core */
  //item.Event_Type = OS_EVENT_NET_CONNECTED;
  //item.data.Net_info.cs_mode = CS_MODE_SERVER;
  //item.data.Net_info.io_select = OS_CONN_CONNECTED;
  //sprintf(item.data.Net_info.name,"%s",Net_node.name);
  //item.data.Net_info.port = Net_node.cs_rmport;
  //item.data.Net_info.socket = newpcb;
  //Enqueue(item);
 }
 return ERR_OK;
}

/*
* Description : The C/S mode Recv callback function
*/
err_t VI_CSMode_Recv(void *arg,struct tcp_pcb *tpcb,struct pbuf *p,err_t err)
{
 struct My_NetList *Net_node;
 Net_node = (struct My_NetList *)arg;
 struct pbuf *q;
 unsigned int data_len = 0;
 char *buffer = NULL;
 err_t  l_unerr;
 MyOS_Node_Def item;
 
 if(p == NULL)
 {
  /* It's a finish info */
  /* send a info to core */
  item.Event_Type = OS_EVENT_NET_CONNECTED;
  item.data.Net_info.cs_mode = Net_node->cs_mode;
  item.data.Net_info.io_select = OS_CONN_CLOSE;
  sprintf(item.data.Net_info.name,"%s",Net_node->name);
  if(Net_node->cs_mode == CS_MODE_CLIENT)  item.data.Net_info.port = Net_node->cs_rmport; // client mode
  else          item.data.Net_info.port = Net_node->cs_loport; // thirdp mode
  item.data.Net_info.socket = Net_node->socket;
  Enqueue(item);
  
  Net_node->socket->callback_arg = NULL;
  Net_node->socket->recv = NULL;
  Net_node->socket->sent = NULL;
  Net_node->socket->errf = NULL;
  Net_node->socket->poll = NULL;
  Net_node->socket->pollinterval = 0;
  if(Net_node->cs_mode == CS_MODE_THIRDP)
  {
   unsigned char length,i;
   length = sizeof(My_NetList)/sizeof(My_NetList[0]);
   for(i = 0 ; i < length ; i++)
   {
    if(Net_node->cs_rmport == My_NetList[i].cs_loport)
    {
     VI_SMode_deleted(&My_NetList[i],Net_node->socket);
     tcp_close( tpcb );
     return ERR_OK;
    }
   }
  }
  Net_node->socket = NULL;
  Net_node->connect_state = CLOSED;
  tcp_close( tpcb );
 }
 else
 {
  buffer = mymalloc(SRAMIN,Net_node->buffer_length);
  if(buffer != NULL)
  {
   memset(buffer,0,Net_node->buffer_length);
   for(q = p; q != NULL ; q = q->next)
   {
    if(q->len > (Net_node->buffer_length - data_len))
    {
     memcpy(buffer + data_len , q->payload , (Net_node->buffer_length - data_len));
    }
    else
    {
     memcpy(buffer + data_len , q->payload , q->len);
    }
    data_len += q->len; 
    if(data_len > CLOUD_RECV_BUFF_SIZE) 
    {
     break;
    }
   }
   tcp_recved(tpcb,p->tot_len);
   pbuf_free(p);
   if(Net_node->Parse != NULL)
   {
    l_unerr = Net_node->Parse(Net_node,buffer,data_len);  // Here we call user parse function
    myfree(SRAMIN,buffer);
    return l_unerr;
   }
   myfree(SRAMIN,buffer);
   return ERR_OK;
  }
  else
  {
   /* maybe memory map is full. add your code here */
   return ERR_OK;
  }
 }
 return ERR_OK;
}

/* ---------------------------------------------------------------------------------------- */
/* -------------------------------------- Box method -------------------------------------- */
/* ---------------------------------------------------------------------------------------- */
struct My_NetList * VI_SMode_insert(struct My_NetList *head,struct My_NetList add)
{
 struct My_NetList *p = NULL;
 p = mymalloc(SRAMIN,sizeof(struct My_NetList));
 if(p != NULL)
 {
  memcpy((char *)p,(char *)&add,sizeof(struct My_NetList));
  p->col_next = head->col_next;
  head->col_next->col_pre = p;
  
  head->col_next = p;
  head->col_next->col_pre = head;
  
  return p;
 }
 return NULL;
}

int VI_SMode_deleted(struct My_NetList *head,struct tcp_pcb *socket)
{
 struct My_NetList *p = NULL;
 
 for(p = head->col_next ; p != head ; p = p->col_next)
 {
  if(p->socket == socket)
  {
   p->col_pre->col_next = p->col_next;
   p->col_next->col_pre = p->col_pre;
   myfree(SRAMIN,p);
   return 0;
  }
 }
 return -1;
}

int VI_CSMode_Broadcast(char *buffer , unsigned short len , char *name)
{
 /* The buffer will be sent to this port */
 unsigned char length,i;
 struct My_NetList *p = NULL;
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 /* First. Find this port. */
 for(i = 0 ; i < length ; i++)
 {
  if(My_NetList[i].cs_mode == CS_MODE_CLIENT)
  {
   /* If it's a client. we should use remote port */
   if(My_NetList[i].connect_state == ESTABLISHED && strcmp(My_NetList[i].name,name) == 0)
   {
    tcp_write(My_NetList[i].socket,buffer,len,TCP_WRITE_FLAG_COPY);
    tcp_output(My_NetList[i].socket);
    break;
   }
  }
  else if(My_NetList[i].cs_mode == CS_MODE_SERVER)
  {
   /* If it's a server. we should use local port */
   if(strcmp(My_NetList[i].name,name) == 0)
   {
    for(p = My_NetList[i].col_next ; p != &My_NetList[i] ; p = p->col_next)
    {
     /* send to all the third-party */
     tcp_write(p->socket,buffer,len,TCP_WRITE_FLAG_COPY);
     tcp_output(p->socket);
    }
   }
  }
  else
  {
   Dbg("It's a illegal C/S mode");
  }
 }
 return 0;
}

int VI_Telenet_Broadcast(char *buffer , unsigned short len)
{
 /* The buffer will be sent to this port */
 unsigned char length,i;
 struct My_NetList *p = NULL;
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 /* First. Find this port. */
 for(i = 0 ; i < length ; i++)
 {
  if(My_NetList[i].cs_mode == CS_MODE_SERVER)
  {
   /* If it's a server. we should use local port */
   if(My_NetList[i].cs_loport == 23)
   {
    for(p = My_NetList[i].col_next ; p != &My_NetList[i] ; p = p->col_next)
    {
     /* send to all the third-party */
     if(p->usrdata.telnet_arg.verf_flag == true && p->usrdata.telnet_arg.Play)
     {
      if( p->usrdata.telnet_arg.Crlf ){
       p->usrdata.telnet_arg.Crlf = false;
       tcp_write(p->socket,"\r\n",2,TCP_WRITE_FLAG_COPY);
      }
      tcp_write(p->socket,buffer,len,TCP_WRITE_FLAG_COPY);
      tcp_output(p->socket);
     }
    }
   }
  }
 }
 return 0;
}

void VI_CMode_IPParse(const char *name, struct ip_addr *ipaddr, void *arg)
{
 struct My_NetList *Net_node;
 Net_node = (struct My_NetList *)arg;
 
 /* dns parse success. here load ip addr to node */
 Net_node->cs_remoteip[3] = ipaddr->addr>>24;
 Net_node->cs_remoteip[2] = ipaddr->addr>>16;
 Net_node->cs_remoteip[1] = ipaddr->addr>>8;
 Net_node->cs_remoteip[0] = ipaddr->addr;
}

/*
 * Echo ( just for telnet ) 
*/
void VI_CSMode_StateEcho(char *buffer,unsigned short buffer_len)
{
 unsigned char length,i;
 char l_byTemparry[500];
 struct My_NetList *p = NULL;
 
 memset(buffer,0,buffer_len);
 sprintf(buffer,"\r\n");
 length = sizeof(My_NetList)/sizeof(My_NetList[0]);
 for(i = 0 ; i < length ; i++)
 {
  if(My_NetList[i].cs_mode == CS_MODE_CLIENT)
  {
   sprintf(l_byTemparry,"+\t\tname:%s\r\n+\t\tmode:client\r\n+\t\tdns : %s\r\n+\t\tstate:%s\r\n+\t\tremote port:%d\r\n+\t\tHeatbeat:%d\r\n\r\n",\
   My_NetList[i].name,My_NetList[i].dns,g_stEthstatus[My_NetList[i].connect_state],My_NetList[i].cs_rmport,My_NetList[i].Heatbeat);
   strcat(buffer,l_byTemparry);
  }
  else
  {
   /* it's server */
   sprintf(l_byTemparry,"+\t\tname:%s\r\n+\t\tmode:server\r\n+\t\tlocal port:%d\r\n\r\n",\
   My_NetList[i].name,My_NetList[i].cs_loport);
   strcat(buffer,l_byTemparry);
   for(p = My_NetList[i].col_next ; p != &My_NetList[i] ; p = p->col_next)
   {
    sprintf(l_byTemparry,"+\t\t\tthird-party\r\n+\t\t\tname:%s\r\n+\t\t\tHeatbeat:%d\r\n\r\n",p->name,p->Heatbeat);
    strcat(buffer,l_byTemparry);
   }
  }
 }
}

My_Bussiness_Init_Register(VI_NetInit,VICON_BUSSINESS_INIT_LEVEL_4);
My_Platform_TimeSlice_Register(VI_NetReconnectCheck,VICON_PLATFORM_1S);
/******************* (C) COPYRIGHT 2019 Doon****************END OF FILE****/

My_TcpManager.h

/********************************************************************************************************
/                                                Doon OS-I
/                                          The Linux-app Wireless manager
/
/
/                         (c) Copyright 2019-2023; Micrium, Inc.; ShenZhen, FL
/                    All rights reserved.  You may obtain a copy of the License at:.
/
/                                        https://me.youkuaiyun.com/weixin_40952498
/
/ File      : My_NetManager.h
/ Version   : V0.00.01
/ By        : Doon
/ Date  : 2019-July 2 Tuesday
/
/ For       : STM32F407VET6
/ Mode      : Thread mode
/ Toolchain : Source Insight 4.0
********************************************************************************************************/
#ifndef _MY_NETMANAGER_H_
#define _MY_NETMANAGER_H_
#include "project.h"

/* <! Client/Server Mode selection > */
#define  CS_MODE_NOTDEF  0
#define  CS_MODE_CLIENT  1  /* < C/S mode -> client > */
#define  CS_MODE_SERVER  2  /* < C/S mode -> server > */
#define  CS_MODE_THIRDP  3  /* < C/S mode -> third-party conn > */
/* <! User data length > */
#define  USR_DATA_LENGTH  50

/* <! Heatbeat  > */
#define  HEATBEAT_NOCOUNT 0xffff
#define  HEATBEAT_DEFAULT 180

typedef union
{
 struct{
  unsigned char  usrname[10];
  unsigned char  password[10];
  unsigned char verf_flag;
  unsigned char  verf_count;
  unsigned char Play:1;
  unsigned char Crlf:1;
  unsigned char Idle:6;
 }telnet_arg;
 
 struct{
  unsigned char mode;
  unsigned char sessionkey[16];
 }bosch_arg;
 /* add usr code here */
 unsigned char by[USR_DATA_LENGTH];
}My_NetUsrArg_Def;

/*  
 The netlist manager map blow to see. The row will be an arrary
 but column will be a linked list
 
 +------+ -next-> +------+ -next-> +------+ -next-> +------+
 |server|         |server|         |client|         |server|
 +------+ <--pre- +------+ <-pre-- +------+ <-pre-- +------+
 ^      |         ^      |                          ^      |
 |      v         |      v                          |      v
 +------+         +------+                          +------+
 |client|         |client|                          |client|
 +------+         +------+                          +------+
 ^      |
 |      v
 +------+
 |client|
 +------+
*/
typedef struct My_NetList
{
 /* < Public variable > */
 char    name[32];   			/* < The socket description > */
 unsigned char   cs_mode;   		/* < Client or server mode > */
 unsigned short  cs_rmport;     	/* < Port of remote socket > */
 unsigned short  cs_loport;     	/* < Port of local socket > */
 const char  *dns;              	/* < dns of connect object(server ignore) > */
 unsigned char  cs_remoteip[4];  	/* < ip-addr of connect object(server ignore) > */
 unsigned char  connect_state;  	/* < Socket state > */
 struct tcp_pcb   *socket;   		/* < ...... > */
 unsigned short  buffer_length;  	/* < the app recv buffer length , will malloc auto > */
 unsigned char  keepalive;   		/* < TCP keepalive flag > */
 unsigned char  suspend;   		/* < suspend > */
 unsigned short  Heatbeat_Setting;	/* < the setting value of heatbeat timer > */
 unsigned short  Heatbeat;   		/* < the heatbeat (if this number eaual 0xffff , the count didn't work) > */
 
 /* < User variable > */
 My_NetUsrArg_Def usrdata;   /*  */
 err_t    (*Parse)(struct My_NetList *node,char *buffer,unsigned short length);   				/* usr parse buffer handler */
 err_t    (*cf_handler)(struct My_NetList *node);           /* connect failed handler */
 
 struct My_NetList *row_next;  	// if we need dynamic expansion
 struct My_NetList *row_pre;
 struct My_NetList *col_next;
 struct My_NetList *col_pre;
}My_NetList_Def;
extern My_NetList_Def My_NetList[];

void VI_NetInit(void);
void VI_NetRelease(void);
int VI_CSMode_Broadcast(char *buffer , unsigned short len , char *name);
void VI_CSMode_StateEcho(char *buffer,unsigned short buffer_len);
int VI_Telenet_Broadcast(char *buffer , unsigned short len);      // for the debug.
struct My_NetList *VI_Net_Getnode(char *name);
int VI_Net_Resume(char *name);
int VI_Net_Suspend(char *name);
int VI_Net_shutdown(char *name);
int VI_Net_HBReset(char *name);
#endif

部分常用的库文件我都添加在"project.h"中,稍后会贴出。
设计思路是想使用二维矩阵链表来对连接进行管理,但是最终我并没有使用动态而是使用了静态数组来进行填表,如果大家有需要可以修改成动态的。- -不知道为什么这里贴出来的代码非常不美观,不太会玩这个编辑器。
下面是我project.h的内容,工程并不是特别大,就直接在一个地方进行管理了,并且附的带了一些调试的接口:

/********************************************************************************************************
/                                                Doon OS-I
/                                          The Doon-app Wireled manager
/
/
/                         (c) Copyright 2019-2023; Micrium, Inc.; ShenZhen, FL
/                    All rights reserved.  You may obtain a copy of the License at:.
/
/                                     https://me.youkuaiyun.com/weixin_40952498
/
/ File      : My project.
/ Version   : V0.00.01
/ By        : Doon
/ e-mail : 1176964408@qq.com
/ Date  : 2019-July 2 Tuesday
/
/ For       : STM32F407VET6
/ Mode      : Thread mode
/ Toolchain : Source Insight 4.0
********************************************************************************************************/
#ifndef __PROJECT_H
#define __PROJECT_H

/*************************************************************************
 *@  type definition
**************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#include "stdint.h"
#include "stm32f4xx_usart.h"
#include "stm32f4xx.h"
#include "stm32f4xx_exti.h"

/* ---------- My OS ---------- */
#include "Doon_Type_Define.h"
#include "LibMacRo.h"
#include "MyOS_Init.h"
#include "MyOS_Tick.h"
#include "MyOS_Handler.h"
#include "MyOS_Core.h"
#include "malloc.h"
#include "rbtrees.h"

/* ---------- My Driver ---------- */
#include "led.h"
#include "key.h"
#include "usart.h"
#include "spi.h"
#include "dp83848l.h"
#include "timer.h"
#include "MacDr.h"
#include "can.h"
#include "rng.h"
#include "iwdg.h"

/* ---------- My Eth driver ---------- */
#include "lwip/opt.h"
#include "lwip_comm.h"
#include "lwip/lwip_sys.h"
#include "lwip/udp.h"
#include "lwip/api.h"
#include "lwipopts.h"
#include "netif.h"
#include "lwip/sockets.h"
#include "lwip/tcp.h"
#include "lwip/err.h"
#include "lwip/dns.h"
#include "lwip/raw.h"

#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/memp.h"
#include "lwip/snmp.h"
#include "lwip/tcp_impl.h"
#include "lwip/debug.h"
#include "lwip/stats.h"

/* ---------- My Device ---------- */
#include "My_DevAbility.h"
#include "My_CAN.h"
#include "My_ExFlash.h"
#include "My_Modbus.h"
#include "My_Power.h"
#include "My_Telnet.h"
#include "My_Led.h"
#include "My_Scene.h"
#include "My_Time.h"
#include "My_DevInfo.h"
#include "My_Rs485.h"

#include "My_Tcp.h"
#include "My_Udp.h"
#include "My_Http.h"
#include "My_Cloud.h"

#include "My_Report.h"
#include "My_NetManager.h"

#include "my_p2m.h"
#include "p2m_configure.h"
#include "p2m_control.h"
#include "p2m_read.h"
#include "My_Json.h"

#include "Can_Update_api.h"
#include "My_Command.h"

/**************************************************************************
 * printf color pain
 * none       = "\033[0m"
 * black      = "\033[0;30m"
 * dark_gray    = "\033[1;30m"
 * blue            = "\033[0;34m"
 * light_blue      = "\033[1;34m"
 * green            = "\033[0;32m"
 * light_green     = "\033[1;32m"
 * cyan            = "\033[0;36m"
 * light_cyan      = "\033[1;36m"
 * red             = "\033[0;31m"
 * light_red       = "\033[1;31m"
 * purple          = "\033[0;35m"
 * light_purple    = "\033[1;35m"
 * brown           = "\033[0;33m"
 * yellow          = "\033[1;33m"
 * light_gray      = "\033[0;37m"
 * white           = "\033[1;37m"
****************************************************************************/
#define  DBG_COLOR_NONE   		"\033[0m"
#define  DBG_COLOR_BLACK    		"\033[0;30m"
#define  DBG_COLOR_DARK_GRAY   		"\033[1;30m"
#define  DBG_COLOR_BLUE    		"\033[0;34m"
#define  DBG_COLOR_LIGHT_BLUE  		"\033[1;34m"
#define  DBG_COLOR_GREEN    		"\033[0;32m"
#define  DBG_COLOR_LIGHT_GREEN  	"\033[1;32m"
#define  DBG_COLOR_CYAN    		"\033[0;36m"
#define  DBG_COLOR_LIGHT_CYAN  		"\033[1;36m"
#define  DBG_COLOR_RED    		"\033[0;31m"
#define  DBG_COLOR_LIGHT_RED   		"\033[1;31m"
#define  DBG_COLOR_PURPLE   		"\033[0;35m"
#define  DBG_COLOR_LIGHT_PURPLE  	"\033[1;35m"
#define  DBG_COLOR_BROWN    		"\033[0;33m"
#define  DBG_COLOR_YELLOW   		"\033[1;33m"
#define  DBG_COLOR_LIGHT_GRAY  		"\033[0;37m"
#define  DBG_COLOR_WHITE   	 	"\033[1;37m"

/**
 * I don't want to recv the warning blow diagnostic messages number 
*/
#pragma diag_suppress 550

/**
* Doon_Dbg == 1: if you wanna open the main switch of debug
*/
#ifndef  Doon_Dbg
#define  Doon_Dbg   1
#endif

#ifndef  Tlenet_Dbg
#define  Tlenet_Dbg   1
#endif

#ifndef  USART_Dbg
#define  USART_Dbg   0
#endif

#if Doon_Dbg
	#if Tlenet_Dbg
		#if USART_Dbg
			#define Dbg(fmt,args...)  do{\
							/*if(MyOS_Status.Telnet_Status == OS_CONN_CONNECTED){*/\
							snprintf(Telnet_Send_Buff,TELNET_SEND_BUFF_SIZE,DBG_COLOR_YELLOW "Doon Dbg " DBG_COLOR_NONE " %s %d: " fmt "\r\n",__FILE__,__LINE__, ## args);\
							VI_Telenet_Broadcast(Telnet_Send_Buff,strlen(Telnet_Send_Buff));\
							/*}else{\
							printf(DBG_COLOR_YELLOW"Doon Dbg" DBG_COLOR_NONE " %s %d: " fmt "\r\n",__FILE__,__LINE__, ## args);\
							}*/\
					}while(0);
		#else
			#define Dbg(fmt,args...)  do{\
							/*if(MyOS_Status.Telnet_Status == OS_CONN_CONNECTED){*/\
							snprintf(Telnet_Send_Buff,TELNET_SEND_BUFF_SIZE,DBG_COLOR_YELLOW "Doon Dbg " DBG_COLOR_NONE " %s %d: " fmt "\r\n",__FILE__,__LINE__, ## args);\
							VI_Telenet_Broadcast(Telnet_Send_Buff,strlen(Telnet_Send_Buff));\
							/*}else{\
							printf(DBG_COLOR_YELLOW"Doon Dbg" DBG_COLOR_NONE " %s %d: " fmt "\r\n",__FILE__,__LINE__, ## args);\
							}*/\
						}while(0);
		#endif
	#else
		#if  USART_Dbg
			#define Dbg(fmt,args...)  do{\
							printf(DBG_COLOR_YELLOW"Doon Dbg" DBG_COLOR_NONE " %s %d: " fmt "\r\n",__FILE__,__LINE__, ## args);\
						}while(0);
		#else
			#define Dbg(fmt,args...)  /* empty printf */
		#endif
	#endif
#else
	#define Dbg(fmt,args...)  /* empty printf */
#endif

//#define REGISTER_CMD(name,maxargs,rep,cmd,usage,help) \            const cmd_tbl_t strcmd_##name __attribute__ ((section ("cmd"))) =  {#name, maxargs, rep, cmd, usage,help}
#endif
/******************* (C) COPYRIGHT 2018 Doon****************END OF FILE****/

仅供参考。
中文使用说明:

/********************************************************************************************************
/                                                Doon OS-I
/                                          The Doon-app Wireled manager
/
/
/                         (c) Copyright 2019-2023; Micrium, Inc.; ShenZhen, FL
/                    All rights reserved.  You may obtain a copy of the License at:.
/
/                                     https://me.youkuaiyun.com/weixin_40952498
/
/ File      : My_TcpManager.
/ Version   : V0.00.01
/ By        : Doon
/ e-mail : 1176964408@qq.com
/ Date  : 2019-July 2 Tuesday
/
/ For       : STM32F407VET6
/ Mode      : Thread mode
/ Toolchain : Source Insight 4.0
********************************************************************************************************/
My Net 框架用例
结构如下:
/*  
 The netlist manager map blow to see. The row will be an arrary
 but column will be a linked list
 
 |------| -next-> |------| -next-> |------| -next-> |------|
 |server|         |server|         |client|         |server|
 |------| <--pre- |------| <-pre-- |------| <-pre-- |------|
 ^      |         ^      |                          ^      |
 |      v         |      v                          |      v
 |------|         |------|                          |------|
 |client|         |client|                          |client|
 |------|         |------|                          |------|
*/
typedef struct My_NetList
{
 /* < Public variable > */
 char    name[32];   /* < 该socket 名字(寻找唯一路径) > */
 unsigned char   cs_mode;   /* < 该socket模式(可选服务端或者客户端) > */
 unsigned short  cs_rmport;   /* < 该socket远端端口号 > */
 unsigned short  cs_loport;   /* < 该socket本地端口号 > */
 const char  *dns;    /* < 域名(仅有客户端存在域名,服务端暂不支持) > */
 unsigned char  cs_remoteip[4];  /* < 远端ip地址(仅有客户端支持,服务端不支持远端ip) > */
 unsigned char  connect_state;  /* < socket连接状态 > */
 struct tcp_pcb   *socket;   /* < socket > */
 unsigned short  buffer_length;  /* < 可自动生成接收buffer的长度 > */
 unsigned char  keepalive;   /* < TCP 保活机制使能位 > */
 unsigned char  suspend;   /* < 该socket挂起标志 > */
 unsigned short  Heatbeat_Setting; /* < 心跳设置周期(根据各协议心跳不一致,需要用户手动调用心跳Reset API) > */
 unsigned short  Heatbeat;   /* < 心跳剩余时间(心跳) > */
 
 /* < User variable > */
 My_NetUsrArg_Def usrdata;   /* < 用户自定义数据 > */
 err_t    (*Parse)(struct My_NetList *node,char *buffer,unsigned short length);   /* 用户解析回调函数 */
 err_t    (*cf_handler)(struct My_NetList *node);           /* 连接失败回调函数(客户端有效) */
 
 struct My_NetList *row_next;  // if we need dynamic expansion
 struct My_NetList *row_pre;
 struct My_NetList *col_next;
 struct My_NetList *col_pre;
}My_NetList_Def;

目前横向使用的是静态数组,纵向使用的环回双向链表,当网关作为服务端时,链表生效,接受第三方设备连入。当网关作为客户端时,链表不生效。(当横向可配置生成时,需修改为横向双向环回链表)
PA:第三方客户端连入网关的name默认为 "ip addr-port" -> "192.168.82.123-10108"(需唯一,用户可自行修改socket name,可修改为第三方网关sn等等)

/* < -------------- API 使用说明 -------------- > */
/*
 描述:无条件广播(用户可以该API为原型完成自定义条件广播,参考Telnet广播)
 buffer: 广播的buffer
 len: buffer的长度
 name: socket名字(当socket名字为服务端时,将发送给该端口下所有连接的客户端,
     当socket名字为客户端时,只发送给连接的服务端
     当socket名字为第三方客户端时,只发送给该)
*/
int VI_CSMode_Broadcast(char *buffer , unsigned short len , char *name);

/*
描述:获取该name节点的所有信息
*/
struct My_NetList *VI_Net_Getnode(char *name);

/*
描述:挂起该socket节点,被挂起后的节点将不再进行自动重连(客户端)
*/
int VI_Net_Suspend(char *name);

/*
描述:恢复该socket节点,被恢复的节点将会自动重连(客户端)
*/
int VI_Net_Resume(char *name);

/*
描述:关闭该socket节点,可填客户端,服务端,第三方节点name
  客户端:关闭客户端,若未挂起该socket,将自动重连
  服务端:关闭服务端下所有第三方连接,不关闭监听,第三方仍然可连入(可完善)
  第三方连接:仅关闭该第三方socket,不影响其他socket。
*/
int VI_Net_shutdown(char *name);

/*
描述:重置心跳,用户协议收到心跳包后应该使用api重置心跳时间
*/
int VI_Net_HBReset(char *name);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值