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

搬运RT Thread中BSD Socket实现UDP及TCP例子

[复制链接]
wofei1314 发布时间:2019-5-8 16:51
1、UDP Client- S* H/ J# L1 Y' e$ s/ g
  1. /* 9 O, M* l- R5 x$ T1 h5 j
  2. * Copyright (c) 2006-2018, RT-Thread Development Team * 3 H! D& C$ _! i% _% q: D
  3. * SPDX-License-Identifier: Apache-2.0 *
      k/ ~0 D5 X+ _0 r
  4. * Change Logs: * Date            
    & a9 X$ `7 |! J" d' N( X& T0 Y
  5. Author      Notes *
    4 I" b) r& k( m/ {! g
  6. */+ z/ R7 d3 r$ f8 W, Z& u
  7. /*
    ' G* p9 M2 ]! p5 a. l/ }) p
  8. * 程序清单:udp 客户端 *
    ' w( l( {6 \0 L, g+ j
  9. * 这是一个 udp 客户端的例程   W' U+ {* n8 z; K
  10. * 导出 udpclient 命令到控制终端 - g1 s% C: b0 r: J
  11. * 命令调用格式:udpclient URL PORT [COUNT = 10]
    4 j! z1 W% l& f6 `
  12. * URL:服务器地址  PORT:端口号  COUNT:可选参数 默认为 10 $ ?1 p" j" B' X
  13. * 程序功能:发送 COUNT 条数据到服务远端9 J  A; Z1 L) h+ R+ e. o( C
  14. */  b- r. M- e- S% j8 G# f% Q
  15. #include <rtthread.h>
    ( K3 O  S: M) L* N
  16. #include <sys/socket.h> /* 使用BSD socket,需要包含sockets.h头文件 */, d, v! r( L5 z) z, @
  17. #include <netdb.h>
    4 _( D, Q, t4 q& `7 F0 X2 ?. F& f
  18. #include <string.h>
    ! V% L, k9 w$ q( o$ ^3 w
  19. #include <finsh.h>  E$ s/ r  s/ W' _& z9 K
  20. 7 Z2 }1 `2 R- ^
  21. const char send_data[] = "This is UDP Client from RT-Thread.\n";1 A9 D0 n5 P( }
  22. /* 发送用到的数据 */: t; L4 h; E  y% u2 k9 V1 ~
  23. void udpclient(int argc, char **argv)/ ^& z8 I, r- F- k. [2 N
  24. {
    5 l" y. Z0 y8 I
  25.     int sock, port, count;8 h& v% ^1 O( S, A3 E- Q
  26.     struct hostent *host;
    - f5 n3 S) F9 Q
  27.     struct sockaddr_in server_addr;8 a% q0 x0 k+ A& e+ o. Y, ~
  28.     const char *url;+ ^1 ^* a+ h9 E$ W( o% s: C% N
  29.     if (argc < 3)% W/ A2 r: f5 ]# w  \# Q! s% D+ j
  30.         {7 d0 |$ N: d! @) R' w# Q
  31.             rt_kprintf("Usage: udpclient URL PORT [COUNT = 10]\n");
    * X' B9 R2 f0 U3 W8 M/ H
  32.             rt_kprintf("Like: tcpclient 192.168.1.9 8000\n");
    + ~+ k  Q. p; e: k' T7 r( w
  33.             return ;
    ( J0 g9 _  f2 s6 }1 T( P) i
  34.         }7 H: z  _  \5 Y1 Y
  35.     url = argv[1];
    / g( W- y' K% V2 K
  36.     port = strtoul(argv[2], 0, 10);
    7 M% a1 ^7 z$ Z' `6 V  h+ y$ I
  37.     if (argc > 3)$ }: T; B& Y4 z2 a
  38.         count = strtoul(argv[3], 0, 10);
    . v7 L% j, N$ @) p) F
  39.     else" S+ d  m  U' I. B* {# x
  40.         count = 10;
    6 s( J3 F: I1 U: w) E
  41.     /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
    ; P2 r! b1 i. k' w9 {9 c
  42.     host = (struct hostent *) gethostbyname(url);5 y% A) L$ f3 @
  43.     /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
    * \! u$ |) Y# j2 ?! ~& q* v; O
  44.     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
    ( r$ u& d$ D8 ~2 e1 j
  45.         {
    , m# L4 R0 O1 Y+ c3 |0 `4 f" P/ a
  46.             rt_kprintf("Socket error\n");
    * }8 e5 `4 |6 L, Y! f' y$ p6 O
  47.             return;) |+ e4 e# D4 x0 k9 B9 [) V" Y
  48.         }$ b0 M7 {! J3 M9 i' g1 v
  49.     /* 初始化预连接的服务端地址 */
    / Z3 G, j5 q! h( ]; f/ y% M
  50.     server_addr.sin_family = AF_INET;
    " S/ \. c  Y6 r" W, H, s- i
  51.     server_addr.sin_port = htons(port);
    6 H: D, J; u. I( {
  52.     server_addr.sin_addr = *((struct in_addr *)host->h_addr);/ d* L4 U; d+ W% H3 \* c
  53.     rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));3 }# E& P$ k9 K
  54.     /* 总计发送count次数据 */
    & Q2 @8 i9 `# G! C) U0 T
  55.     while (count)7 w8 @5 G7 \1 S- }7 f! t. C
  56.         {  Q( F/ ?; ?1 J6 x
  57.             /* 发送数据到服务远端 */1 d! K8 j, O1 [) E0 {
  58.             sendto(sock, send_data, strlen(send_data), 0,               (struct sockaddr *)&server_addr, sizeof(struct sockaddr));0 q) |0 U+ c/ f6 q$ \! l
  59.             /* 线程休眠一段时间 */
    ( I# J: W3 T- Y5 A" B& O" a
  60.             rt_thread_delay(50);( N* Q! C! ^( {
  61.             /* 计数值减一 */
    9 u% l: R6 g& j0 c. A+ j
  62.             count --;' L7 E- u3 f. r" W
  63.         }
    ( P  A' h$ C0 u  m; S0 S
  64.     /* 关闭这个socket */
    + g5 C, S# ]/ E8 _
  65.     closesocket(sock);
    3 }9 U/ g1 Q$ W& d' u& {; O6 B
  66. }
    4 {6 q( r; g/ `3 a# t' T) A( ]
  67. MSH_CMD_EXPORT(udpclient, a udp client sample);
    , Q6 Y; P) B2 C5 w9 Z4 ]
  68. 6 _+ c) p- s( O2 Y( }& e; w: j; q; h
复制代码
2、UDP Server
" K3 t/ `  Y! `2 z1 `/ h
  1. #include <rtthread.h>
    0 e+ b1 Z4 P+ j! H
  2. #include <sys/socket.h>
    3 k& ]* T3 N3 T% D
  3. /* 使用BSD socket,需要包含socket.h头文件 */
    , m0 V( T' U; k; J: x: v1 ?
  4. #include <netdb.h>7 {8 g* K/ _  d$ T0 S1 e
  5. #include <string.h>: f. b% z& [5 C7 K/ S: w
  6. #include <finsh.h>
    ! l7 ]3 H& K. A/ d9 l
  7. #define BUFSZ   1024' N0 k! K! `9 j; A0 g
  8. static void udpserv(int argc, char **argv)
    + V$ V; |6 h6 J
  9. {. s7 s7 Z" i9 M6 c3 M
  10.     int sock;
    , ?( ^1 [7 X0 g! U
  11.     int bytes_read;$ P. D3 V1 {! L+ y: Z6 b: @# a
  12.     char *recv_data;
    5 X$ S+ D  h3 _9 C
  13.     socklen_t addr_len;
    7 n5 Z# w) S5 t, J7 O0 H
  14.     struct sockaddr_in server_addr, client_addr;2 I) m1 H2 w" S) V4 E; f8 F* I
  15.     /* 分配接收用的数据缓冲 */+ w$ q: U  _7 y( R* I( c5 m
  16.     recv_data = rt_malloc(BUFSZ);
    % B2 H. B$ K* t9 ]
  17.     if (recv_data == RT_NULL)
    0 Z: w) X5 v8 x; S% Z0 J, b, U
  18.         {* F2 g! v  @# [2 d
  19.             /* 分配内存失败,返回 */        
    2 D5 z- L+ x8 C$ j# ~! D. `- V
  20.                         rt_kprintf("No memory\n");
    ( K" k3 ?6 ?& y  y/ b. j; V
  21.             return;" \% n' h* f4 G+ @& L
  22.         }, L. m" c; n' E4 i. p4 @
  23.     /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
    ! S- Q0 q. j5 q
  24.     if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)4 `6 X; j( y0 q
  25.         {
    % t6 h2 U* K. Q# t" ?% X: p8 G
  26.             rt_kprintf("Socket error\n");
    ; f( l4 S( t+ d
  27.             /* 释放接收用的数据缓冲 */        
    7 U6 C) A0 x5 @3 S2 g, E
  28.                         rt_free(recv_data);6 c4 W4 f. }( u
  29.             return;4 a2 B6 ?/ j* H0 I. `/ k
  30.         }
    ! f" [2 d2 ?. F9 L
  31.     /* 初始化服务端地址 */$ P( Z$ }8 ]5 ~! B# |% b5 |5 x
  32.     server_addr.sin_family = AF_INET;
    & |2 W# c% d+ o% W0 |: b& M
  33.     server_addr.sin_port = htons(5000);; _0 w5 o! [, q9 [
  34.     server_addr.sin_addr.s_addr = INADDR_ANY;
    ! E" u" T% _8 f6 s
  35.     rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
    . ^- a0 r9 _+ i: l& J3 A
  36.     /* 绑定socket到服务端地址 */
    ' u/ Z5 C7 ^$ T" m+ c) J! B! W6 v
  37.     if(bind(sock, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)
    1 C+ o4 b' E( s/ X2 |3 T9 ~3 X, o) s
  38.         {0 e% ^2 R: k" a$ z# d+ R) I: i
  39.             /* 绑定地址失败 */& v- w' F- P. _' ~! M
  40.             rt_kprintf("Bind error\n");
    - u! G1 A/ e+ c% \- T( K% k
  41.             /* 释放接收用的数据缓冲 */
    - ?7 r  l/ v" d( F. |) \9 \+ e3 }
  42.             rt_free(recv_data);
    ! _, m8 x% @' I
  43.             return;( a( L) o  V- ~/ c3 ]! ^
  44.         }
    1 x# v( t1 y0 e4 z% j- l
  45.     addr_len = sizeof(struct sockaddr);
    + y0 Y; ~3 {  s
  46.     rt_kprintf("UDPServer Waiting for client on port 5000...\n");
    % I/ d6 h" V! [
  47.     while (1)+ f; O: b1 j$ C( Y
  48.         {9 P$ |# \' m1 M8 {- v2 a
  49.             /* 从sock中收取最大BUFSZ - 1字节数据 */. f0 ^1 f8 L- N+ {+ I3 _  O
  50. % p" V6 x& P7 J
  51.             bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0,
    1 ?7 |, B% t7 N+ m6 Q! T" X
  52.                                   (struct sockaddr *)&client_addr, &addr_len);
    ! r/ A, c5 R7 Z* V+ l, h1 X
  53.             /* UDP不同于TCP,它基本不会出现收取的数据失败的情况,除非设置了超时等待 */
    + J% B  J" _4 c( |0 f8 {) v! P! v
  54.             recv_data[bytes_read] = '\0';         /* 把末端清零 */8 i( c7 o6 Q# G8 P! U2 j
  55.             /* 输出接收的数据 */
    - `* M0 u! \# E; V
  56.             rt_kprintf("\n(%s , %d) said : ", inet_ntoa(client_addr.sin_addr),
    5 U" O: o, g( P; w% H5 _6 D. x$ t. q2 @
  57.                        ntohs(client_addr.sin_port));
    % u6 O$ H0 L/ E' l
  58.             rt_kprintf("%s \n", recv_data);
    ' o& \6 v" w$ P0 Q1 V
  59.                         //udp 用 sendto 函数发送% x' D/ F$ Q! B, G  {
  60.                         sendto(sock,recv_data,bytes_read,0,(struct sockaddr *)&client_addr,addr_len);- A) N# B! C% u+ o2 U
  61.             /* 如果接收数据是exit,退出 */        , S9 @" ?0 K, V- l5 f3 a
  62.                         if (strcmp(recv_data, "exit") == 0)
      V$ E1 }  c! U4 m0 `5 ]
  63.                 {
    5 `/ S) K( \$ J# |+ S7 @  ?
  64.                     closesocket(sock);            /* 释放接收用的数据缓冲 */% v0 w0 Y4 `) s$ t; H2 u  r
  65.                     rt_free(recv_data);
    5 C3 f6 K. `8 I7 |5 z" R: h; i
  66.                     break;
    ' B- K% `& E$ U9 D
  67.                 }
    4 y. t' h3 J# v" {
  68.         }* o9 T  o; r, n/ b5 O& V- l* R% n
  69.     return;
      o, q0 i+ m+ c/ ~/ z  D
  70. }
    & n8 l& ]% U& v9 P& F' l* n

  71. / a7 f4 @& S9 |
  72. MSH_CMD_EXPORT(udpserv, a udp server sample);
    , B' t$ n; G/ ~; x
复制代码
3、TCP Client* o3 C2 [9 W8 b# m8 \& J
  1. /*
    ; t& M5 \6 `) @% e( Z# m
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
    5 z  F+ U- ]2 u- \: J
  3. *
    # d5 v& |# l: G) Z  `& d0 D
  4. * SPDX-License-Identifier: Apache-2.0 *
    " c. {% k* W; J' B
  5. * Change Logs:
    ) ^! p. J! D) g* Y( g5 P
  6. * Date             Author      Notes *; q6 U+ l# ?6 r
  7. */
    ) a% h9 }% F2 k) C- m
  8. /*
    : R2 f% s( ?9 \3 L
  9. * 程序清单:tcp 客户端9 C; H# Q. S4 @+ Q9 I' G
  10. ** z7 M$ @% x3 V+ u
  11. * 这是一个 tcp 客户端的例程" n, `- X( z& w% v0 f
  12. * 导出 tcpclient 命令到控制终端+ ]+ t# l' g# P# g
  13. * 命令调用格式:tcpclient URL PORT
    0 {& n. h9 b* a/ T
  14. * URL:服务器地址 PORT::端口号7 [. e) Z$ w+ I3 i6 q/ O
  15. * 程序功能:接收并显示从服务端发送过来的信息,接收到开头是 'q' 或 'Q' 的信息退出程序& j9 q0 _$ ~/ \8 I  {& z" b3 g
  16. */; m2 Z) y# C1 U* A& i4 T
  17. #include <rtthread.h>/ ^& X" N" ?5 k- D
  18. #include <sys/socket.h>
    5 i: D9 i- A8 Q" p
  19. /* 使用BSD socket,需要包含socket.h头文件 */0 f$ S, Z8 W+ P4 J& E- ^1 }) E
  20. #include <netdb.h>
    $ \+ w! y. k0 a: S7 `
  21. #include <string.h>
    ; R2 `) {6 s4 U0 j
  22. #include <finsh.h>. i! o0 t, f& }, o. V
  23. #define BUFSZ   1024
    ( t' c0 j5 J8 }3 x7 N) l% a5 k5 R
  24. static3 g; Y# Z4 x4 L* P
  25. const char send_data[] = "This is TCP Client from RT-Thread.";& p) N1 m2 y7 g. W
  26. /* 发送用到的数据 */1 y' p- Z* L) K8 j- h
  27. void tcpclient(int argc, char **argv)
    7 j+ C/ p0 p1 x0 [& h7 s
  28. {
    - ~: @: o' K8 s# G
  29.     int ret;; K& E$ G+ O8 E+ \6 D. Q5 [, J
  30.     char *recv_data;
    2 G( p7 {3 M$ c3 p$ t- E. m
  31.     struct hostent *host;
    " Q% f+ R* d; i  }3 @
  32.     int sock, bytes_received;5 E# {  u2 I3 S& b" B
  33.     struct sockaddr_in server_addr;
    % {# f3 A1 l- g! B  d- W
  34.     const char *url;
    8 [# }* c: `$ s$ Z
  35.     int port;
    9 j0 K; P( Y, e4 \1 q
  36.     if (argc < 3)) s% G8 @: U( B) R" F, y
  37.         {
    * m) m8 x: O; \' b
  38.             rt_kprintf("Usage: tcpclient URL PORT\n");
    7 f; E$ Q+ a1 v! s1 l
  39.             rt_kprintf("Like: tcpclient 192.168.12.44 5000\n");$ o) ]7 ~/ K+ U  O) A$ _5 Z' R
  40.             return ;
    , d2 A8 m! H  k. [5 \6 V# z
  41.         }
    7 ]0 e5 U' x0 i7 S1 Q! @$ h
  42.     url = argv[1];
    * j: Z% I; K' ~/ I
  43.     port = strtoul(argv[2], 0, 10);
    $ d, U4 a. G* g4 A$ A
  44.     /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */9 |# e: m: d8 H0 p8 x2 s
  45.     host = gethostbyname(url);
    9 T% t  K7 s+ b2 T4 f, F& v
  46.     /* 分配用于存放接收数据的缓冲 */8 [8 ^$ {1 o: P
  47.     recv_data = rt_malloc(BUFSZ);
    ; F- X. k: p) u; L  d; k
  48.     if (recv_data == RT_NULL)! ]3 ]- L# B( h3 j3 E" g: o- [7 _
  49.         {6 j& h; H# `8 C1 J0 X% R
  50.             rt_kprintf("No memory\n");
    # y8 ?, s# K" C8 N
  51.             return;4 ?* L" u( G) p2 N
  52.         }
    5 c! i7 T7 g( ~6 ]
  53.     /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */
    2 @3 y1 H8 l% X) V" y
  54.     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1); r" C2 x# w8 S: X8 a% s7 Y
  55.         {% H  ]  O. k' w8 q6 G$ \7 \
  56.             /* 创建socket失败 */
    3 I% ?) [5 ?$ n
  57.             rt_kprintf("Socket error\n");
    : T# x3 j3 X/ ~9 E3 ~
  58.             /* 释放接收缓冲 */
    2 g- Z. s" W/ P+ P! R1 m- t, R
  59.             rt_free(recv_data);
    ! E5 {" h  U  k1 ]+ v
  60.             return;
    ; _( Y/ w9 V. P/ [6 ]
  61.         }( x1 X- G1 t+ L9 p3 l* t4 l
  62.     /* 初始化预连接的服务端地址 */
      H7 k2 {6 i7 {. t
  63.     server_addr.sin_family = AF_INET;
    $ Z6 |; ?4 _7 U0 d! T& ?
  64.     server_addr.sin_port = htons(port);
    7 s$ n% Q  [* v
  65.     server_addr.sin_addr = *((struct in_addr *)host->h_addr);$ k( @  L$ i) Q8 u/ z2 k
  66.     rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
    3 A/ P8 R& t1 }  I3 K
  67.     /* 连接到服务端 */' l) X9 f3 y# u. e
  68.     if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)1 y8 Z8 t4 y, p  I! {6 G: `( c
  69.         {
    4 H, K6 p$ g* U$ ~# P
  70.             /* 连接失败 */  e- P( O) N2 j& ~+ c0 ]: n5 |/ C) K
  71.             rt_kprintf("Connect fail!\n");
    , z2 d( B$ I. m9 }1 J- n- V' a
  72.             closesocket(sock);
    $ A! N6 e5 c+ R+ Q# O
  73.             /*释放接收缓冲 */& U4 x9 C; r- u" s- y  V9 i! `2 Y& ~
  74.             rt_free(recv_data);5 ?, \$ B4 U* ]& [+ h, f, J
  75.             return;
    6 |; _: K  L+ X- N1 V( t9 W
  76.         }
    0 P. t% o2 a2 k
  77.     while (1)5 E  o+ ]$ s! }! ]3 E# o! `& M( e
  78.         {
    % o$ T2 i  Q5 Y3 e
  79.             /* 从sock连接中接收最大BUFSZ - 1字节数据 */" ^) C; A' U" t. x) ^
  80.             bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);2 I* j7 V4 O' Y* l
  81.             if (bytes_received < 0)
    6 f6 ^9 f1 x. `9 f
  82.                 {, w/ c1 m  h) |3 k
  83.                     /* 接收失败,关闭这个连接 */2 O9 F# P4 |* F# H+ D3 {
  84.                     closesocket(sock);- w9 [& S1 _' `' F! m
  85.                     rt_kprintf("\nreceived error,close the socket.\r\n");
    " f4 N; S7 B" q, W  U" J" Z* t
  86.                     /* 释放接收缓冲 */
    3 [2 l4 ~& n# `
  87.                     rt_free(recv_data);
    ! N0 K& V. U8 g. r8 _' y7 l( N
  88.                     break;  u2 w# d# u! ~( M
  89.                 }
    5 o" [8 @# z3 I4 W3 G2 K0 v' ?# Z7 N
  90.             else if (bytes_received == 0)
    ! g' Z1 \- U+ D8 B/ U2 B8 ~0 `$ ^& H
  91.                 {
    : N: e8 f& W) v. P9 u! n
  92.                     /* 默认 recv 为阻塞模式,此时收到0认为连接出错,关闭这个连接 */
    ! ~$ v% U1 F  N6 w# ]
  93.                     closesocket(sock);/ y/ n( N9 v- W: Q/ C, _
  94.                     rt_kprintf("\nreceived error,close the socket.\r\n");6 ?- Y1 p4 K- F2 r
  95.                     /* 释放接收缓冲 */
    4 B, k0 h/ W& `: Q, e+ M/ d  c
  96.                     rt_free(recv_data);% c- ]$ @) Q6 `. B
  97.                     break;
    * ~3 \1 d1 K! B: e
  98.                 }0 @, {3 t; B; m6 S2 Z8 e
  99.             /* 有接收到数据,把末端清零 */
    + f( y  G# R2 A% p) Z2 t
  100.             recv_data[bytes_received] = '\0';
    . r  h' N2 A: p3 ?0 G- g
  101.             if (strncmp(recv_data, "q", 1) == 0 || strncmp(recv_data, "Q", 1) == 0)
    ( k& w# }. F6 C% N: A( d
  102.                 {
    + E" b% A1 f8 |8 _4 Q
  103.                     /* 如果是首字母是q或Q,关闭这个连接 */
    2 O- p  ~* ~% x5 Q5 ?0 I  {
  104.                     closesocket(sock);  K8 L( l# u8 e, i, S+ K) ~/ {, X
  105.                     rt_kprintf("\n got a 'q' or 'Q',close the socket.\r\n");
    ) m9 n2 d3 m% ]9 R, n; E
  106.                     /* 释放接收缓冲 */
    & ]8 G2 C" U1 P5 E
  107.                     rt_free(recv_data);
    7 D6 W$ ]; q7 u$ u! X; S9 x
  108.                     break;
    7 B9 V- z8 }: v
  109.                 }
    & ]# Q: ?, e( Q
  110.             else
    * l8 t" V) @1 N2 _) ]3 }
  111.                 {
    & ^* }" A' C' C" ^3 ]% U$ x
  112.                     /* 在控制终端显示收到的数据 */
    & r7 K' R) q0 q! |1 ^
  113.                     rt_kprintf("\nReceived data = %s ", recv_data);
    4 j$ F: X7 x" F) h" d% g! d
  114.                 }        /* 发送数据到sock连接 */
    8 o+ q9 u9 `( e" w! E6 }
  115.             ret = send(sock, send_data, strlen(send_data), 0);
    % J1 L% w. g! u7 k$ Y- p9 Q% D) H
  116.             if (ret < 0)
    ) w5 [. X  u# u# M. P1 ^
  117.                 {2 ]& K6 Q0 |5 r* c; L$ Q
  118.                     /* 接收失败,关闭这个连接 */+ J; R' I; W1 K
  119.                     closesocket(sock);
    ; Z/ K* N7 a! ~: [+ W1 k0 n8 }
  120.                     rt_kprintf("\nsend error,close the socket.\r\n");2 j6 Z) z3 Y3 A- R
  121.                     rt_free(recv_data);
    : a! T& o# P9 ^3 M$ {$ ]% ~9 S
  122.                     break;
      }/ O/ j+ v+ c, r8 ]
  123.                 }
    8 F8 R& _4 G: l" l" _5 K9 J6 e
  124.             else if (ret == 0)/ M, d: \5 K7 f. w9 x. Z# r
  125.                 {" ]  h5 a8 h- q  D0 f, p: p
  126.                     /* 打印send函数返回值为0的警告信息 */
    ) U3 E3 t  x7 N) d% ]& ?
  127.                     rt_kprintf("\n Send warning,send function return 0.\r\n");9 o" E# m9 h( {) c
  128.                 }' L2 }' L8 C' H& i2 j
  129.         }
    % {. H0 l' x* k0 e& l( u3 i
  130.     return;
    3 n5 P1 t% z" W4 @/ b9 D
  131. }$ {& n9 |& Z. f( u7 _  [# p
  132. MSH_CMD_EXPORT(tcpclient, a tcp client sample);
    0 L( G2 P  Y4 F, x1 B, s
复制代码
4、TCP server2 A5 ~2 [6 ~0 l( _8 B
  1. /*
    # T  {, c4 O8 D4 a* B
  2. * Copyright (c) 2006-2018, RT-Thread Development Team& N* a7 j0 q7 o
  3. *
    # x! [+ s' P1 E
  4. * SPDX-License-Identifier: Apache-2.0& K. F; S7 J3 ^$ H
  5. *) y8 {$ [. m  n0 j  U
  6. * Change Logs:
    ! k% h# L7 d. ]: m6 l0 F
  7. * Date             Author      Notes2 W% S. H- P, r7 h. z9 N+ s
  8. *
    5 [  U) z/ T7 L6 o- a
  9. */
    , f" G  p/ b% @
  10. /*1 A; l6 m9 E* K9 h$ t) o9 `
  11. * 程序清单:tcp 服务端
      Z; V( B: O5 Z+ _+ v8 Y; z( u
  12. *
    - j3 i- I* j9 h+ U4 e: I5 \! \" M" R+ ^
  13. * 这是一个 tcp 服务端的例程; k# U# F( V( w& u1 J
  14. * 导出 tcpserv 命令到控制终端0 F, ?- A1 K1 a4 X+ N
  15. * 命令调用格式:tcpserv6 {7 v* h( f/ l3 k, W; B9 H2 h; L
  16. * 无参数
    4 W8 F% y1 L: b$ i6 d- e
  17. * 程序功能:作为一个服务端,接收并显示客户端发来的数据 ,接收到 exit 退出程序
    / G9 l* c" A  }7 ~4 }' @
  18. */
    , K8 l& e7 @5 p& d* {5 v
  19. #include <rtthread.h>
    * i" {& _* N# B5 l( J# }* Z
  20. #include <sys/socket.h>+ G0 O6 o# D  {/ J3 y; n
  21. /* 使用BSD socket,需要包含socket.h头文件 */
    7 L$ h+ E4 B$ b# D+ K4 P
  22. #include <netdb.h>
    ) p+ i/ F( w! ^$ {# {) C
  23. #include <string.h>. X, ^( ~! W) Y1 i6 `' [+ O) }
  24. #include <finsh.h>9 K0 {9 |" v, h9 s( z( w) W
  25. #define BUFSZ       (1024)
    / g; [  L4 s; @0 t# ~5 E
  26. static const char send_data[] = "This is TCP Server from RT-Thread.";% }& E% K& a" U
  27. /* 发送用到的数据 */
    - K- F7 u/ f* t7 d  P+ G, X& y& M
  28. static void tcpserv(int argc, char **argv)
      y- U4 y8 Y2 e* {7 W# P6 W$ r6 i
  29. {
    / B* z% r5 r8 o$ L
  30.     char *recv_data;
    . u: ~% F+ X) k
  31.     /* 用于接收的指针,后面会做一次动态分配以请求可用内存 */
    3 A2 i2 v' w/ a- E% J) G
  32.     socklen_t sin_size;. a1 M# M' ^) F1 _3 |! ~
  33.     int sock, connected, bytes_received;
    ( y" Q0 z7 _6 j* E" _$ M
  34.     struct sockaddr_in server_addr, client_addr;7 `* g$ @2 s: D- x
  35.     rt_bool_t stop = RT_FALSE;
    ' E9 X: [9 u9 l7 a& c' s
  36.     /* 停止标志 */
    & G0 ~. l$ [: m9 C& Q6 L- ^$ s
  37.     int ret;
    - }7 u' q2 U4 v+ b& K; ^4 y. g
  38.     recv_data = rt_malloc(BUFSZ + 1);0 m2 }5 f, t- _% @6 [& p) E3 j5 L% y
  39.     /* 分配接收用的数据缓冲 */9 s# O! ?0 e- ?! l5 a+ x6 L' J
  40.     if (recv_data == RT_NULL)
    5 r/ Y/ V8 A- a1 p$ c6 ]& O, b, }
  41.         {
    9 X- Y5 N5 T( g. E5 z
  42.             rt_kprintf("No memory\n");# I& g# P9 k) l0 J6 n3 n
  43.             return;
    # w7 l* n% \7 X3 K
  44.         }
    ' i3 G& X& u( `6 A3 ]
  45.     /* 一个socket在使用前,需要预先创建出来,指定SOCK_STREAM为TCP的socket */
    0 R& }# _  m8 d# j: p% A
  46.     if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)# w$ D; d, k/ R0 F6 S  x
  47.         {
    - @4 D6 o4 }% ^/ J% s
  48.             /* 创建失败的错误处理 */
    - L1 Z% d5 D) Y( I

  49. * `' A2 P6 L8 S7 S: h
  50.             rt_kprintf("Socket error\n");! ~+ ?2 H! V# A  Z
  51.             /* 释放已分配的接收缓冲 */9 z7 I! `) k' ^! }5 k
  52.             rt_free(recv_data);
    2 {1 o! @4 s' q& F1 A7 S2 M/ ?
  53.             return;* F: [+ q* j6 }& t
  54.         }
    9 L4 ~2 ?4 X: r% V4 j
  55.     /* 初始化服务端地址 */1 K4 W1 z& C7 M% Q# f' f
  56.     server_addr.sin_family = AF_INET;% b4 K* K" S5 C9 H) |: j) G- ~! P
  57.     server_addr.sin_port = htons(5000);
    2 ~6 \2 n1 L" ~& y6 j
  58.     /* 服务端工作的端口 */
    ; Q& D$ z5 {: k# n2 V( H; q
  59.     server_addr.sin_addr.s_addr = INADDR_ANY;8 w7 c9 ~& y) O: Y, ?8 w' \
  60.     rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
    , f+ S5 j: ?) g; t
  61.     /* 绑定socket到服务端地址 */0 {0 n2 a1 v2 R  ]
  62.     if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)3 Q; C8 Y: f1 p: ]& e% C8 B1 v
  63.         {4 X4 O( ^6 `8 B# i. [5 k8 N
  64.             /* 绑定失败 */% f) z( T5 a2 N9 A  N( m
  65.             rt_kprintf("Unable to bind\n");
    , O, ]# ^6 ?2 d1 N$ H% H; F) s3 ^
  66.             /* 释放已分配的接收缓冲 */
    6 j; \2 h. `) Y# v6 {" {/ d
  67.             rt_free(recv_data);8 _! L/ p! d! Q/ b. ^
  68.             return;$ p6 s5 P, Y7 n% K: K
  69.         }. d. r4 k. V9 }5 D
  70.     /* 在socket上进行监听 */
    4 W4 u, l" k( W9 O
  71.     if (listen(sock, 5) == -1)6 }  k7 b! {5 }; T, s2 Y3 |
  72.         {1 W8 |' x: Y4 t. c; g) g" ?1 r+ s
  73.             rt_kprintf("Listen error\n");
    " U% J- c# ]- T. [/ ?7 K; ^& W  d
  74.             /* release recv buffer */! h2 d: h* R, m3 S6 z& e' c# u* W
  75.             rt_free(recv_data);4 o3 _( Q3 I" Z4 E; I! I
  76.             return;
    9 d: I  x; @# Q4 m0 X/ r
  77.         }( N% Y/ q' M8 ^; S/ d$ a
  78.     rt_kprintf("\nTCPServer Waiting for client on port 5000...\n");
    3 d; P" R2 ^& t5 `$ x% m
  79.     while (stop != RT_TRUE); j9 a- I# p9 M6 d1 M# Y
  80.         {
    - _8 X6 R3 e$ [3 @. |' N
  81.             sin_size = sizeof(struct sockaddr_in);- [. ]- M3 F$ [- E2 P3 F
  82.             /* 接受一个客户端连接socket的请求,这个函数调用是阻塞式的 */
    + [. H: L$ N; t% x; Q. G. K
  83.             connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size);- Q- m9 d" r5 B8 G8 F6 F+ z6 N
  84.             /* 返回的是连接成功的socket */7 d" C4 U$ f) k" o" }
  85.             if (connected < 0)! [7 S7 U- |! Z) d; T7 i
  86.                 {
    4 h# x& H0 \9 B: ]" Q/ d
  87.                     rt_kprintf("accept connection failed! errno = %d\n", errno);
    3 q  [0 s3 H" e* ^
  88.                     continue;' e$ e* h; i1 l
  89.                 }5 ~4 D  z. Q, ]8 J: v2 q
  90.             /* 接受返回的client_addr指向了客户端的地址信息 */
    + u  P& @0 f& z0 E7 @
  91.             rt_kprintf("I got a connection from (%s , %d)\n",, ~# b% D& x; D4 \+ @" Y, I$ x; m* o
  92.                        inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));, F& J7 b4 v2 j2 Q
  93.             /* 客户端连接的处理 */
    ! A9 \0 p. Z$ r1 m
  94.             while (1)
    4 z1 ]# q- l1 Y, h8 I  _- p# l
  95.                 {( X6 S1 U- U" R: Z( z
  96.                     /* 发送数据到connected socket */. O  P$ f: ?3 V' G
  97.                     ret = send(connected, send_data, strlen(send_data), 0);
    2 k0 ]  X0 Y6 e+ w* K
  98.                     if (ret < 0)
    * D" F. }# U& f$ P- C
  99.                         {) @1 [8 L7 v( }6 `4 f5 X
  100.                             /* 发送失败,关闭这个连接 */
    / g  B' N: x% T0 X0 [$ l$ a; P  U4 c
  101.                             closesocket(connected);
    # w3 D$ t" Q* b8 y, E% l" U1 [' b
  102.                             rt_kprintf("\nsend error,close the socket.\r\n");8 x4 F8 J, [! h6 k
  103.                             break;  }+ u2 h3 J+ Q. s( \
  104.                         }8 X  \4 K( D: X- G( x9 @* j# s9 {0 b
  105.                     else if (ret == 0)
    ( r/ O- E# \9 v
  106.                         {- k7 @0 P8 N; W9 _5 X8 s
  107.                             /* 打印send函数返回值为0的警告信息 */
    . N6 X% l4 o  f' L' _7 }2 ^
  108.                             rt_kprintf("\n Send warning,send function return 0.\r\n");
    . f7 N0 Q/ t& X% X
  109.                         }! a. @( t& C% |0 G7 R$ q( J. e0 u- y
  110.                     /* 从connected socket中接收数据,接收buffer是1024大小,但并不一定能够收到1024大小的数据 */6 j/ c/ T" n$ `0 H
  111.                     bytes_received = recv(connected, recv_data, BUFSZ, 0);
    $ O1 l2 ?1 Y( z) D
  112.                     if (bytes_received < 0)1 L6 d$ i3 S: S2 I  W& l: z
  113.                         {/ _7 X# Q0 o8 ?0 @+ u
  114.                             /* 接收失败,关闭这个connected socket */) G5 }+ h, y1 g* s5 g
  115.                             closesocket(connected);
    4 T8 Y8 I+ l0 M; L
  116.                             break;
    0 M6 c) e8 u9 H- W5 {
  117.                         }
    * Y. e1 y# l: R7 \$ B6 ?5 {
  118.                     else if (bytes_received == 0)( \9 C; G  n, o/ t  \3 {+ e' o1 U
  119.                         {5 V5 I4 l! t* [$ N6 k8 F9 `$ ?
  120.                             /* 打印recv函数返回值为0的警告信息 */+ T7 Y7 I5 F/ F+ }
  121.                             rt_kprintf("\nReceived warning,recv function return 0.\r\n");# t6 x$ J+ Q; k. f
  122.                             closesocket(connected);4 b! Y8 l3 v& A5 h, P; N
  123.                             break;
    7 Y( f8 V8 n/ ~5 i- v# W3 K
  124.                         }
    : r+ a: q7 Y/ J$ [7 g- ]
  125.                     /* 有接收到数据,把末端清零 */' J$ N, P( j( L7 t! j7 ~
  126.                     recv_data[bytes_received] = '\0';
    % b+ u+ o* A* t7 j2 x# Y" O6 g
  127.                     if (strcmp(recv_data, "q") == 0 || strcmp(recv_data, "Q") == 0)
    # w( O2 ~  d8 N
  128.                         {' y: ~/ Z9 ?5 \+ n- g
  129.                             /* 如果是首字母是q或Q,关闭这个连接 */
    / X; k) W" a: H* _- }9 F' d
  130. / h* e# T0 z2 ~% B
  131.                             closesocket(connected);# R0 d7 u0 ~& @! g/ b9 x; S; x! D
  132.                             break;, Z: |2 H' L% }$ n6 h. E; d& v9 J
  133.                         }( A7 }! }" D- D$ i$ S; @
  134.                     else if (strcmp(recv_data, "exit") == 0)% o. H" _1 O; Y
  135.                         {
    # S9 ?. u2 @6 A, j& `* J8 v0 L& [
  136.                             /* 如果接收的是exit,则关闭整个服务端 */- p+ Z$ E! ^# x6 p( Q5 j
  137.                             closesocket(connected);$ \) |: C) [* l
  138.                             stop = RT_TRUE;, e2 Y7 Z3 m" q# s- k5 `. z
  139.                             break;
    0 Y  S+ y& X+ D4 {$ `) |
  140.                         }: K( G3 e2 R$ Q+ h. y# P
  141.                     else* u, B' F, S' o( R" v3 d8 K2 b4 n
  142.                         {
    4 z5 K9 A% g  N7 s, f1 t4 ^5 O" p* }
  143.                             /* 在控制终端显示收到的数据 */
    ' X6 _0 ~% p& T
  144.                             rt_kprintf("RECEIVED DATA = %s \n", recv_data);
    , e' l# V7 U: f! X9 c+ G5 `
  145.                         }( Q  [$ l5 r# D6 R
  146.                 }  s/ a( B% o. h% E) J' b: c
  147.         }    /* 退出服务 */$ `6 K  N# j' i$ y
  148.     closesocket(sock);0 R' s& P# R; k$ g
  149.     /* 释放接收缓冲 */
    , x+ `8 W2 v. Z5 z
  150.     rt_free(recv_data);7 n% e% s! G% n& F% O% i
  151. & B2 Y" c3 P1 x( b- D" f" ~
  152.     return ;
    . j  z! P' k9 a; b+ {& X
  153. }; Y5 o( {  Z- M. h# s8 a
  154. MSH_CMD_EXPORT(tcpserv, a tcp server sample);
复制代码

6 M; y& }" d3 ?* n# D
6 O" S+ M3 Z2 k搬运过来,给需要的朋友~( _; j+ I% d/ n9 M, J3 \# E2 W
收藏 1 评论2 发布时间:2019-5-8 16:51

举报

2个回答
yklstudent 回答时间:2019-5-9 08:39:04
感谢分享
damiaa 回答时间:2019-5-9 08:44:27
感谢分享

所属标签

相似分享

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