你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

一个简单的 TCP 客户端测试程序

[复制链接]
murphyzhao 发布时间:2019-6-27 09:26
本帖最后由 murphyzhao 于 2019-6-28 08:53 编辑 ( `" Y2 O1 F* Y, G- f; P
$ [! Q  ?: ~* f& i. F
现在都 lwip 210 版本了,无奈,因为客户 SDK 的原因还在捣鼓 lwip151 版本。
3 ?7 S, l1 I1 m4 @& s$ k5 s
! j# J$ [1 f4 s+ x4 L0 c. f将客户 SDK 升级到 RT-Thread 系统的时候,发现低功耗部分与 LWIP 有耦合,不能直接使用 RT-Thread 移植的 LWIP 组件,也就意味着,我不同享受 RT-Thread netdev 组件和 SAL 组件开发的便利。
, w' O0 F" @; ~3 j9 d9 s
+ u% J, u1 b/ J, L  {/ G" E于是,给自己挖了个坑,把 LWIP151 版本对接到 netdev 和 sal 组件上
  C" I* W* u' S' m) r+ P- T/ N  a0 D/ W- ]' o1 v# c* r5 E
为了测试,捣鼓了一个简单的 TCP 客户端程序,后面有时间也把对接 RT-Thread netdev 组件和 SAL 组件的过程也给分享出来。
8 N/ E' P0 `7 y5 \- g7 _
9 P' R: _7 s" |! w这里提供的代码基于 BSD-type 风格的 socket 函数接口,你可以在任何支持 BSD socket 的平台上使用这段程序,当然这段程序也可以在包含了 RT-Thread SAL 的使用方法,引入 SAL 相关头文件。6 z+ M) I' ^6 h  W* Y
4 _5 `% i4 S" G# e& s
  1. #include <stdio.h>
    8 m( C2 e7 u4 J9 G8 o
  2. #include <string.h>
    ; x% o# r$ r4 a7 X/ q! Y( l
  3. #include <rtthread.h>+ P) T! j1 Y; z  H& v7 z

  4. . P2 P* a1 q+ q: U/ [" C
  5. /* 引入 lwip socket 头文件 */6 L: a, p7 y6 ~
  6. #include "lwip/sockets.h"
    ; \' U8 f4 N# U
  7. #include "lwip/netdb.h"
    5 S- I3 g* j- z1 v4 [7 D
  8. #include "lwip/sys.h"
    $ u; A4 `2 E: m5 S  e+ g5 O: l

  9. , N7 e) B, I% k7 g1 ^
  10. #define TCP_TEST_HOST    "your host or ip addr" /* 输入你的 TCP server 域名或者 ip 地址 */2 N( t/ u8 M( T& [( U
  11. #define TCP_TEST_PORT    (80u)                  /* 输入你的 TCP Server 断口号 */9 G4 G2 _+ Y. j% a
  12. #define TEST_BUFSZ       (1024u)2 w6 U' A+ V2 {
  13. ! ?. V! s+ U6 b( D/ _1 ^
  14. static const char *send_tcp_req_data = "Hi, I am from tcp client.";  H) z7 s' l# H4 @3 ?, ?1 ]# |
  15. . g; v' I5 J6 R% m% Q
  16. static void _tcp_test(void)
    / `) q, R$ l$ e0 T# E# ?
  17. {
    # C( U) i9 L$ ~! ^  D: p* ~; w
  18.     int ret, i;3 l6 L4 [- B" h5 d& F' ^3 K
  19.     char *recv_data;# J+ o! E5 C: @% }6 l' k3 W
  20.     struct hostent *host;. X" M- F- b0 |* R
  21.     int sock = -1, bytes_received;
    ( a4 L8 b7 z6 R
  22.     struct sockaddr_in server_addr;/ A& P9 ?% t6 c4 X* b
  23. " Z0 ~/ X$ D' y5 W. \% w( U1 n
  24.     /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
    0 [; k+ \3 L. }5 j* b0 Z2 j  o
  25.     host = gethostbyname(TCP_TEST_HOST);
    0 S) M. f; y0 K- |7 |4 O
  26.     if (!host)
    7 {4 |5 ^4 \1 h5 G9 r
  27.     {
    : T/ u  L2 c4 K8 R1 U
  28.         rt_kprintf("gethostbyname failed!\r\n");0 D3 Y! m  v7 B/ Z# Z0 L
  29.         return;
      F  u' F; L/ S/ V0 P* W
  30.     }3 \& n' G/ m; ^/ e1 ^3 l
  31.     else
    * X- B, e5 Z6 q! L9 n& B
  32.     {" `8 P! W% h, _: ?$ h3 s
  33.         rt_kprintf("gethostbyname success!\r\n");
    1 m" ^0 B2 b, J, {0 a9 W: b3 p4 j4 {
  34.     }% Q8 J1 R0 q' G/ G& F7 o8 ]
  35. % Y5 F4 i3 k: v7 N& |: f
  36.     recv_data = calloc(1, TEST_BUFSZ);) H; Y, m5 ?9 c+ E6 K& m$ R9 ]% k5 n
  37.     if (recv_data == RT_NULL)
    + u, z0 z+ _8 u/ X# Z9 Z
  38.     {
    ; K' M7 x% P+ r# {4 E
  39.         rt_kprintf("No memory\n");
    - i+ n0 c2 c6 S+ B; J, L4 R* Z! ~& R
  40.         return;" Y2 V% D8 u8 s9 h
  41.     }& ~4 a* c) z3 d! L

  42. ( g; V& a' H, I9 P  ]# }
  43.     /* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */7 X' F; y. C6 G# R
  44.     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    0 f) h2 `8 C5 C
  45.     {1 L1 w8 W$ R, p2 x4 g/ h
  46.         rt_kprintf("Socket error\n");  O8 p( M( o$ f+ R! v5 ^: m* t2 }" }
  47.         goto __exit;
    & i& J- l7 ~) b/ C* G$ @5 v( C% `
  48.     }/ v* ]' e5 O  I" _
  49.     else
    $ R: O7 p) ~" F0 ^" T/ X/ f# g
  50.     {
    0 K# v2 j( N4 ]& ~
  51.         rt_kprintf("Socket pass\n");
    ) |( M) C3 T9 |2 v% M- l/ L% ~
  52.     }
    ( e/ Q* ]3 o  K& E: u. x! x+ {- ~

  53. - ?9 }4 E7 A& W, F) \$ C
  54.     /* 初始化预连接的服务端地址 */, H7 O5 o' J0 T$ p6 ^# `% n( X
  55.     server_addr.sin_family = AF_INET;
    ) u: b' U! U! s$ A
  56.     server_addr.sin_port = htons(TCP_TEST_PORT);
    7 @- r3 @2 o+ q% u6 F! m) [
  57.     server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    1 b0 \* G3 A* s( ?% Q* j
  58.     memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
    ' C0 d# t+ l# f) z2 {6 |
  59. 1 \# }, u2 d- c- |% g& V
  60.     rt_kprintf("will connect...\n");
    / [6 I3 v$ ?" G5 J& f# [* M% E* F
  61.     if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)& V* X& ?; j: S. O* e- {2 ]7 B
  62.     {
    ; g8 ~2 Q* H9 @2 J
  63.         rt_kprintf("Connect fail!\n");+ o7 P  z  O/ y2 ^. f' _6 I" R/ }
  64.         goto __exit;
      b3 W0 ^* Z. h! j# g( w9 m0 L
  65.     }
    # B7 |, E, W) h+ ?/ b. C/ Z2 [
  66.     else( J2 G" z& M! v) H
  67.     {7 H2 W7 N( G$ b1 n# M6 V: O! e
  68.         rt_kprintf("Connect pass!\n");
    ) W3 H# H) R& K2 L* C. A$ I
  69.     }# Y) N  `/ y! e: I& d7 P

  70. " X( A$ E' c2 E6 ?+ }7 D2 Y
  71.     /* 发送数据到 socket 连接 */9 i+ Z5 f6 Z. `3 X+ J& @
  72.     ret = send(sock, send_tcp_req_data, strlen(send_tcp_req_data), 0);
    * a: M0 J& _6 J/ K7 b0 I" B
  73.     if (ret <= 0)
    ' E5 H; S6 w, s0 x8 R( _( v
  74.     {3 n& `; z4 \7 `) B2 r; ?
  75.         rt_kprintf("send error,close the socket.\n");5 ~' s6 M+ l" J* V( k. W- B) Y$ E1 V
  76.         goto __exit;' R# _! _" G0 i8 B' v" `" n
  77.     }: T! |$ A( f' L8 O0 r( `# L
  78.     else
    ; V  T( Q9 f' y  q+ I  C5 o
  79.     {/ Y* y3 T# S6 T7 J
  80.         rt_kprintf("send pass!\n");2 Q' q* H( x% w
  81.     }
    / S( s. a  w2 l* d

  82. ! j2 }; Z5 P. O6 K! z
  83.     /* 接收并打印响应的数据,使用加密数据传输 */
    8 B- Q0 `9 ^/ |, R* y, H) B- b
  84.     bytes_received = recv(sock, recv_data, TEST_BUFSZ - 1, 0);0 X( ?: t7 M1 l7 D* Q' y
  85.     if (bytes_received <= 0); m+ I) h& l" {/ Y
  86.     {/ ^9 S# i/ b0 V9 e, \
  87.         rt_kprintf("received error,close the socket.\n");4 X% p! R' o5 Y* \0 t+ t* T
  88.         goto __exit;2 m8 \' p- `, i* s# f' I3 W
  89.     }
    + @' X3 o, Q! c7 N$ z
  90. * q' Y$ N( Q- @4 Q; w0 n
  91.     rt_kprintf("recv data:\n");/ B0 k) P# g' H! F# q
  92.     for (i = 0; i < bytes_received; i++)
    - L7 @4 g# S' c$ M6 r
  93.     {
    " L4 D1 _* X0 i% i$ O7 M5 I2 E
  94.         rt_kprintf("%c", recv_data);
    ; x- F2 Q& c$ C; @4 h
  95.     }9 K& y7 T5 T2 f
  96. 3 S* R: o/ Z& {
  97. __exit:0 A& j" b7 T" X0 n8 D
  98.     if (recv_data)
    8 e3 \5 i2 H6 h. Z
  99.         rt_free(recv_data);
    1 S& Z1 X7 j- b  a- @) y& h7 e
  100. / Q9 D3 }* o' b+ b9 M; g
  101.     if (sock >= 0)
    6 b( O/ k. ~" F* x- a
  102.         close(sock);
    # ]( x$ f6 p! |% D3 z
  103. }
    % _7 b# Z# G& U% n
  104. 6 J% e: u! j& K2 ?1 Z# H5 O. |
  105. void tcp_test(void)
    : E) c3 S) U. E8 e/ B
  106. {5 I, b( I- h4 ^" Q! O
  107.     rt_thread_t tid;
      {  l8 g0 Y7 c% a  C
  108.     tid = rt_thread_create("tcp", _tcp_test, NULL, 4096, 23, 5);5 N- d4 L4 k' f: I
  109.     if (tid)
    / M" y9 y& T1 |$ x/ @3 W5 |
  110.         rt_thread_startup(tid);
    . T9 f7 h; }2 `
  111.     else
    ! r% a% g5 ]. ~1 r! {0 N
  112.     {( K* [! s. p- G1 x" s0 m: w* x
  113.         rt_kprintf("tcp thread create failed!\r\n");) d: u7 N- a& W4 c3 d; `( G. J
  114.     }
    $ h! U$ ~( L! k$ _) V
  115. }$ z, o" `( |  F% \* x& s
  116. 3 \2 P1 l. T( P8 l  S& A/ ~! o/ P2 G) y+ b
  117. #ifdef FINSH_USING_MSH: J* D: s/ J2 t3 W
  118. #include <finsh.h>
    7 R8 H; j; n9 i& ?% U
  119. MSH_CMD_EXPORT(tcp_test, TCP function test);
    + u0 M# k8 F% a) z, r) N" L$ X
  120. #endif /* FINSH_USING_MSH */
    ' u& g3 s4 c$ @5 T7 _* U4 @
复制代码

* R1 z) I0 J0 r9 ~$ [. Q; K
- h6 S& R/ f9 I如果你也是使用 RT-Thread,那么直接复制代码加入编译,然后在 MSH 中运行既可以:% L2 m- j( E3 K% g: `

! N1 P  f, b; I
  1. msh /> tcp_test
复制代码
tcp_client.rar (1.32 KB, 下载次数: 3)
收藏 评论1 发布时间:2019-6-27 09:26

举报

1个回答
murphyzhao 回答时间:2019-6-28 08:56:29
之前粘贴的代码有问题,这下学会怎么插入代码了。: d- q3 j4 M& B: t
9 w- l  o0 [' l& ~8 S. ?6 r
从文本编辑器复制代码,粘贴到论坛里的代码插入标签,提交之后会插入到当前光标位置。0 ]3 O8 R. ~  v& h/ U8 ^
这个时候你看到的代码格式是乱掉的,没有空格缩进等,不要紧,保存提交帖子即可,这个时候会发现,代码格式显示正常了。

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版