OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5919|回复: 5

freertos TCP Client无法连接Server

[复制链接]

3

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2019-4-26
在线时间
15 小时
发表于 2021-6-29 16:28:17 | 显示全部楼层 |阅读模式
5金钱
我在STM32F407上搭建TCP客户端,打算让它连接PC上的服务器,但每次启动时connect一直不成功。于是我就打开PC上的cmd终端,ping下客户端,发现是通的,奇怪的现象就出现了:ping完客户端后,客户端马上就能connect上服务器了。。试了几次都是这样,郁闷,请问大家知道这是啥原因导致的?

客户端IP:192.168.11.77
服务端IP:192.168.11.37

服务端软件:串口调试助手上的网络服务器功能
客户端代码:
  1. #include "tcp_client.h"


  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <memory>


  6. #include <cmsis_os.h>
  7. #include "FreeRTOSIPConfig.h"
  8. #include "FreeRTOS_IP.h"
  9. #include "FreeRTOS_Sockets.h"

  10. #include "data/data.h"
  11. #include "generate_protocol/search_protocol/search_protocol.h"
  12. #include "protocol/message.h"
  13. #include "protocol/protocol.h"
  14. #include "protocol/node_id.h"
  15. #include "package.h"

  16. #define MAX_HEART_COUNT                5        //单位xReceiveTimeOut


  17. struct freertos_sockaddr TcpServerAddress;
  18. static const TickType_t xReceiveTimeOut = pdMS_TO_TICKS( 2000 );
  19. static const TickType_t xSendTimeOut = pdMS_TO_TICKS( 1000 );
  20. Socket_t xSocket;
  21. Recivebuff recivebuffes;
  22. TaskHandle_t TCPTest_TaskHandle;
  23. int try_count = 0;
  24. int heart_miss_count = 0;

  25. // 连接函数
  26. int TcpClientConnect(void)
  27. {
  28.         int ret = 0;
  29.         // 每次连接之前逻辑清空接收数组
  30.         recivebuffes.length = 0;
  31.        
  32.         // 填充目标端口和IP地址
  33.         Data* data = Data::GetInstance();
  34.         unsigned short port = data->GetPort();
  35.         TcpServerAddress.sin_port = FreeRTOS_htons(port);
  36.         TcpServerAddress.sin_addr = FreeRTOS_htonl(data->GetRemoteIP());
  37.          
  38.         // 创建套接字
  39.         xSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP );
  40.         configASSERT( xSocket != FREERTOS_INVALID_SOCKET );

  41.         // 设置超时
  42.         FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) );
  43.         FreeRTOS_setsockopt( xSocket, 0, FREERTOS_SO_SNDTIMEO, &xSendTimeOut, sizeof( xSendTimeOut ) );
  44.        
  45.         // 连接
  46.         ret = FreeRTOS_connect( xSocket, &TcpServerAddress, sizeof( TcpServerAddress ) );
  47.        
  48.         return ret;
  49. }

  50. // 断开连接
  51. void TcpClientDisconnect(void)
  52. {
  53.         TickType_t xTimeOnEntering;
  54.         BaseType_t xReturned;
  55.        
  56.         // 关闭连接
  57.         FreeRTOS_shutdown( xSocket, FREERTOS_SHUT_RDWR );
  58.        
  59.         // 检查连接是否断开
  60.         xTimeOnEntering = xTaskGetTickCount();
  61.         do
  62.         {
  63.                 xReturned = FreeRTOS_recv( xSocket, recivebuffes.cRxBuffers, sizeof(recivebuffes.cRxBuffers), 0 );
  64.                 if( xReturned < 0 )
  65.                 {
  66.                         break;
  67.                 }
  68.         }
  69.         while( ( xTaskGetTickCount() - xTimeOnEntering ) < xReceiveTimeOut );
  70.        
  71.         // 关闭套接字
  72.         FreeRTOS_closesocket( xSocket );
  73.        
  74. }

  75. // 发送函数
  76. int TcpClientSend(char *pSendBuff,uint32_t lBuffLen)
  77. {       
  78.         BaseType_t lTransmitted;
  79.        
  80.         // 发送数据
  81.         lTransmitted = FreeRTOS_send(xSocket,pSendBuff,lBuffLen,0 );
  82.         //vTaskDelay(150 / portTICK_PERIOD_MS);
  83.        
  84.         if(lTransmitted < 0)
  85.         {
  86.                 return 0;
  87.         }
  88.         else
  89.         {
  90.                 return 1;
  91.         }
  92. }

  93. // 接收函数
  94. void TcpClientRecive(void)
  95. {
  96.         BaseType_t lrecive;
  97.        
  98.         // 接收数据
  99.         memset(recivebuffes.cRxBuffers, 0, sizeof(recivebuffes.cRxBuffers));
  100.         lrecive = FreeRTOS_recv(xSocket, recivebuffes.cRxBuffers, sizeof(recivebuffes.cRxBuffers), 0);
  101.         if(lrecive <= 0 )
  102.                 recivebuffes.length = 0;
  103.         else
  104.         {
  105.                 recivebuffes.length = lrecive;
  106.         }
  107. }

  108. void TcpClientThread(const void *parameter)
  109. {

  110.         auto send_to_pc = [](const std::string& data) ->void
  111.         {
  112.                 TcpClientSend((char *)data.c_str(), data.size());
  113.         };
  114.        
  115.         do{
  116.                 if(TcpClientConnect() == 0)
  117.                 {
  118.                         try_count = 0;
  119.                         while(1)
  120.                         {
  121.                        
  122.                                 vTaskDelay(2000 / portTICK_RATE_MS );

  123.                         }
  124.                 }

  125.                 TcpClientDisconnect();
  126.                 vTaskDelay(3000 / portTICK_RATE_MS );
  127.                
  128.         }while(++try_count);
  129.        

  130.         vTaskDelete(xTaskGetCurrentTaskHandle());
  131. }
  132. BaseType_t xReturned;
  133. void Heart_Handler(const void *parameter)
  134. {


  135.         while(1)
  136.         {
  137.                 if(FreeRTOS_issocketconnected(xSocket))
  138.                 {
  139.                         memset(recivebuffes.cRxBuffers, 0, sizeof(recivebuffes.cRxBuffers));
  140.                         xReturned = FreeRTOS_recv(         xSocket,                                        /* The socket being received from. */
  141.                                                                         recivebuffes.cRxBuffers,                /* The buffer into which the received data will be written. */
  142.                                                                         sizeof(recivebuffes.cRxBuffers),                /* The size of the buffer provided to receive the data. */
  143.                                                                         0 );

  144.                                                 }
  145.                 else
  146.                 {
  147.                         vTaskDelay( 1000 / portTICK_PERIOD_MS );
  148.                 }

  149.         }

  150.         vTaskDelete(xTaskGetCurrentTaskHandle());
  151. }

  152. int CreateTcpThread(void)
  153. {

  154.     osThreadDef(TcpTask, TcpClientThread, osPriorityNormal, 0, 1024);
  155.     osThreadCreate(osThread(TcpTask), (void*)0);

  156.         osThreadDef(HeartTask, Heart_Handler, osPriorityNormal, 0, 700);
  157.     osThreadCreate(osThread(HeartTask), (void*)0);

  158.         return 0;
  159. }
复制代码


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1023
金钱
1023
注册时间
2019-9-21
在线时间
269 小时
发表于 2021-6-29 19:39:04 | 显示全部楼层
回复

使用道具 举报

3

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2019-4-26
在线时间
15 小时
 楼主| 发表于 2021-6-30 11:01:59 | 显示全部楼层
客户端连不上时,错误码返回是pdFREERTOS_ERRNO_ETIMEDOUT,即连接超时。
通过抓包发现,客户端connect时第一包SYN握手都没发出来。。
回复

使用道具 举报

15

主题

1061

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
3606
金钱
3606
注册时间
2019-8-14
在线时间
1052 小时
发表于 2021-6-30 12:29:51 | 显示全部楼层
把防火墙全部关闭,网络适配器只留下要连接的IP的适配器,别的适配器关闭看下
回复

使用道具 举报

3

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2019-4-26
在线时间
15 小时
 楼主| 发表于 2021-6-30 14:08:47 | 显示全部楼层
hou18 发表于 2021-6-30 12:29
把防火墙全部关闭,网络适配器只留下要连接的IP的适配器,别的适配器关闭看下

PC防火墙一直是关着的,适配器也有试过只留下“以太网”,但还是一样的现象。
我试过局域网内手机TCP软件连接PC上的服务端,是可以正常连接的
回复

使用道具 举报

3

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
51
金钱
51
注册时间
2019-4-26
在线时间
15 小时
 楼主| 发表于 2021-7-1 10:23:10 | 显示全部楼层
我debug发现:
/* Determine the ARP cache status for the requested IP address. */
eReturned = eARPGetCacheEntry( &( ulRemoteIP ), &( xEthAddress ) );
eReturned返回的是eARPCacheMiss,也就是说ARP缓存中没找到该服务器IP地址,当我ping客户端的时候,ARP缓存中就出现服务器IP,于是就顺利连接上了?
但是没道理呀,难道每次都要先让服务器下发数据给客户端,才能保证后面正常连接?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-27 14:34

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表