本帖最后由 murphyzhao 于 2019-6-28 08:53 编辑
) {, o" e% Z2 v* I' \9 ^ ~7 K2 R
现在都 lwip 210 版本了,无奈,因为客户 SDK 的原因还在捣鼓 lwip151 版本。
% q( L" f1 K( r9 k/ V( s% H# q& ?8 L" h/ H$ w& l8 A! u
将客户 SDK 升级到 RT-Thread 系统的时候,发现低功耗部分与 LWIP 有耦合,不能直接使用 RT-Thread 移植的 LWIP 组件,也就意味着,我不同享受 RT-Thread netdev 组件和 SAL 组件开发的便利。9 `9 H, i8 f8 N0 A( H& G- h
- P a; p9 }. H
于是,给自己挖了个坑,把 LWIP151 版本对接到 netdev 和 sal 组件上
, l' y& j O( C2 X
: u! I" F8 l2 S3 n5 z为了测试,捣鼓了一个简单的 TCP 客户端程序,后面有时间也把对接 RT-Thread netdev 组件和 SAL 组件的过程也给分享出来。
- t* n( b* w+ I& n7 h; ?4 Q% @; c* v7 T6 _! y' H+ ]" X
这里提供的代码基于 BSD-type 风格的 socket 函数接口,你可以在任何支持 BSD socket 的平台上使用这段程序,当然这段程序也可以在包含了 RT-Thread SAL 的使用方法,引入 SAL 相关头文件。$ }' U7 C9 a# g4 B: @& r: E
) Q" K* Z8 O& _% \" c9 k
- #include <stdio.h>
- T" d1 F" [6 ~* G' D - #include <string.h>
# f0 o$ k& u6 n9 ~( Y - #include <rtthread.h>
; w: f* q2 ], N2 ?) ` - 9 V* j% N" |) F( K
- /* 引入 lwip socket 头文件 */
3 j% z/ Y8 Q+ m e) ~ - #include "lwip/sockets.h"- B3 y2 e# |8 F: w& W! S
- #include "lwip/netdb.h"1 f8 h' @2 n9 i7 K
- #include "lwip/sys.h"
) z# D2 I6 ^0 z! T& D/ Y" ? - N( h P. d( B" K! U2 C& k
- #define TCP_TEST_HOST "your host or ip addr" /* 输入你的 TCP server 域名或者 ip 地址 */
+ J- o; ^ \7 x( G9 N( ?" l - #define TCP_TEST_PORT (80u) /* 输入你的 TCP Server 断口号 */
, A$ f% A# s! G( o7 u - #define TEST_BUFSZ (1024u)
6 _! l' a3 c* Z6 V. j( w3 M - $ W) I7 x \- }3 G
- static const char *send_tcp_req_data = "Hi, I am from tcp client.";2 b7 A7 r' C; J% C% W! H
- h$ ^4 ^4 U# Q9 |- static void _tcp_test(void)
+ }2 R! Z' v& J. k - {4 i6 A, Y% i; z o7 D
- int ret, i;
p2 |4 N0 A' K" z w - char *recv_data;" H* |5 t) m$ |0 U' [$ ^/ B. B( t
- struct hostent *host;' I3 B% B. M+ w
- int sock = -1, bytes_received;! {% v, |* ~2 {: R/ }2 n+ h
- struct sockaddr_in server_addr;& S$ W; @- d0 Y
- $ a, F& S! S' i, ?5 V3 N* Q
- /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
% a* y; `" T1 q7 P+ c - host = gethostbyname(TCP_TEST_HOST);" ^6 d: _/ O2 y, M. O7 G$ R
- if (!host)
4 Z9 j7 L) T1 P - {
) S* V3 n: p- N; d* I9 ] - rt_kprintf("gethostbyname failed!\r\n");7 Q$ @1 G( t6 v2 I4 n+ c
- return;. K& A# T. v3 ^- ~% e, r& v
- }5 { X }; \' P* }5 w3 n9 n
- else
3 A, F) n' l. T( x) z - {- e; f& M B" A
- rt_kprintf("gethostbyname success!\r\n");( G9 x# P% S1 `; |) A2 s9 n# M! H
- }9 W7 v4 @$ |$ M( p) B0 e, @
- c" k4 X% h6 U' ~. j
- recv_data = calloc(1, TEST_BUFSZ);8 w: ]( s% ?6 P0 }( l, Q+ }
- if (recv_data == RT_NULL)
( M4 ~$ z' @% @; y6 ~5 Q - {$ v+ J9 N, ^$ B: r5 k2 K
- rt_kprintf("No memory\n");# M% k6 J6 f5 t. ^
- return;; G% m, s% W+ k. p
- }: ~* c( H/ l4 z7 x, X' v
- 2 e) b+ l& J+ K- t. ~
- /* 创建一个socket,类型是SOCKET_STREAM,TCP 协议, TLS 类型 */; k$ C, m$ h$ R% @8 h" a1 G# ?0 J. W
- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) k9 E# c, L) s5 V3 P
- {2 c# v. K, N" }5 p% U. e
- rt_kprintf("Socket error\n");
& n- z) t# A1 P, X& R, O8 V - goto __exit;
7 j a: u7 N, V' v' S, b - }
+ O$ u2 q- k% l) o. o" i" U. ? - else' y% ~9 y- h6 h3 j, ?
- {
s# k6 R- j: k! L# C; }7 z B - rt_kprintf("Socket pass\n");
2 k! [( d: ^+ `" f5 E* O9 r - }
; ?4 m2 j* k5 c7 K% Z! H5 J
3 F: q/ M% z( Z5 e$ {/ a- /* 初始化预连接的服务端地址 */
8 d! l6 L3 U7 n - server_addr.sin_family = AF_INET;
' j$ Z( H+ V6 H, ~* m - server_addr.sin_port = htons(TCP_TEST_PORT);! p: o' [, T4 B$ i
- server_addr.sin_addr = *((struct in_addr *)host->h_addr);
- N& h, V# e6 ?7 V U- z0 E - memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
M! R. X$ T. C- R6 x& `# M$ i9 o - 5 I6 \. m+ c9 t, u; h; p1 R
- rt_kprintf("will connect...\n");+ X) S- ]7 G0 D; v& F
- if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
+ p9 b; B" ]3 @9 C: c2 Q# ] - {
( \* G0 R- {" B& ^2 j& B% _ - rt_kprintf("Connect fail!\n");' U Q3 f3 M( h
- goto __exit;
9 ^7 U, [* }/ n7 z - }
: q! ]3 m* r" v - else3 ~/ _* g- f1 V' ^* Q* V" d# p
- {: ~/ p6 Z+ p$ o' o) C
- rt_kprintf("Connect pass!\n");0 n2 J) w& T# _" Q; `
- }( v9 o; ~4 \, g1 B9 e, Y; _
y* Z6 v/ y5 N; A" [3 v4 [- /* 发送数据到 socket 连接 */
$ |( i" e2 }. v6 w/ Y! L8 Y1 o - ret = send(sock, send_tcp_req_data, strlen(send_tcp_req_data), 0);
/ q: v& [" T* J, E" K. K' v* N0 x) V5 X - if (ret <= 0)
+ w( B8 n1 P U& l - {
( } f- L- M [, r/ E/ R - rt_kprintf("send error,close the socket.\n");
@& s/ o0 Y" k# L H! g+ O( l - goto __exit;" ]8 q6 O$ x2 |0 \
- }/ Q. o) }/ R. u: [
- else
( h1 D( V8 K1 j, w - {
3 B( ^8 Q5 n0 l. q - rt_kprintf("send pass!\n");
9 Y, q/ H# w9 ]1 [0 n9 Q9 v- u - }7 N& e5 s+ o1 r1 T- o/ _, |
- 9 k0 p) g/ q* _6 ?6 o1 D' l
- /* 接收并打印响应的数据,使用加密数据传输 */! t8 ^& }+ V2 F$ L' ]- l
- bytes_received = recv(sock, recv_data, TEST_BUFSZ - 1, 0);" }" Z3 l6 S4 J
- if (bytes_received <= 0)
9 O2 V I8 M2 b- U - {
3 u0 {# \& k# N& `5 x1 j - rt_kprintf("received error,close the socket.\n");0 s6 G. N+ {* C2 ?
- goto __exit;) ~4 _- W+ x1 ^& q1 z' o" c5 M
- }
* `. L9 E/ J% Y/ Z - " O' [6 @8 B) S, v: w( ^
- rt_kprintf("recv data:\n");8 J: t8 S* W9 P
- for (i = 0; i < bytes_received; i++)7 J3 E1 z! I5 q& z8 H
- {
6 Z) k n/ F$ F' Z - rt_kprintf("%c", recv_data);
" x: f9 P1 d7 s# a% j0 V8 T$ z" k7 D/ Y - }! { B' t! t3 `* q7 D+ x9 g5 Z
- % g# f, ^. U# {1 V' o t. A* ?
- __exit:
# \0 H; o4 X6 R - if (recv_data)
; o( T: _" _ ^* \4 {" W0 i - rt_free(recv_data);
) p2 U5 T: t# e& L; d1 Q- A0 N - + ~+ P6 u9 v, I
- if (sock >= 0)" n0 t2 d8 j+ e; |# F c% s
- close(sock);; n( r2 o# p6 }' b% p9 [: r
- }
. |* e( {4 v! B l* ^ - 9 ]- j& f5 Y d! V, J- w
- void tcp_test(void); B0 s: E, r' U+ M0 B% q
- {
- T, Z5 d) V$ a$ G/ C S- w0 N - rt_thread_t tid;
& p0 ?: G5 E! f: c/ K0 ^% E - tid = rt_thread_create("tcp", _tcp_test, NULL, 4096, 23, 5);+ m% M6 e9 T+ ?- M+ p* J! Z" O- V
- if (tid)/ M* k! Y! b) H, d; h
- rt_thread_startup(tid);
+ h3 t5 W2 \5 b# Z - else& Y% i8 A# ^6 f: @' ?" g
- {1 B+ Q7 K W7 n; {$ `! Y4 x
- rt_kprintf("tcp thread create failed!\r\n");
! l' J# N! P ^3 a# P+ v3 o3 R: ^ - }
& D: ?9 \6 g' g9 ^% u - }# l- E' r; f6 {1 w
- 4 Y, S# R7 W+ k
- #ifdef FINSH_USING_MSH
' m0 e1 P* _; O4 I - #include <finsh.h>
7 h. E( r5 @7 O9 [4 v - MSH_CMD_EXPORT(tcp_test, TCP function test);) }* E" g* ~9 F- n# G
- #endif /* FINSH_USING_MSH */, D0 [+ \- ?# k" I0 v
复制代码
7 \/ T( C" z' h; ?- b7 O9 ~2 t0 |; E+ J9 C# E7 A5 ] b8 G7 a5 z
如果你也是使用 RT-Thread,那么直接复制代码加入编译,然后在 MSH 中运行既可以:, W5 l6 f0 r9 b6 O2 [5 @* |
0 | z9 L- U0 @, j8 \2 k, b
tcp_client.rar
(1.32 KB, 下载次数: 3)
|
6 j$ @+ @7 i$ Z2 v1 m
从文本编辑器复制代码,粘贴到论坛里的代码插入标签,提交之后会插入到当前光标位置。0 q. M2 R! }4 Y& K8 C- i0 M
这个时候你看到的代码格式是乱掉的,没有空格缩进等,不要紧,保存提交帖子即可,这个时候会发现,代码格式显示正常了。