管理员
论坛积分
分
威望 点
贡献值 个
金币 枚
|
沙发
楼主 |
发表于 2020-5-9 01:48:09
|
只看该作者
服务端启动,客户端通过ip地址连接服务端,然后输入要发送的文件名,发送文件到服务段.6 t' ?3 }; _& H9 e4 }0 ~
- /*client.c*/
& ^% D+ C6 h% T( b8 M6 I - #include<netinet/in.h> // for sockaddr_in
2 o* v0 R* ^4 G1 X - #include<sys/types.h> // for socket 4 m+ H* `# C) V+ S
- #include<sys/socket.h> // for socket & k" H" v* l2 j4 N: H, P
- #include<stdio.h> // for printf
. ? M6 n/ |' c. _' s - #include<stdlib.h> // for exit
, f5 g8 C! ?9 b$ U) Z - #include<string.h> // for bzero * U9 V; ^& j9 W4 I' m
- 9 p/ w* T3 I, \' j: @
- #define HELLO_WORLD_SERVER_PORT 6666 & ~# l( L2 x: z
- #define BUFFER_SIZE 1024 ( l2 f3 x3 Z( K( t
- #define FILE_NAME_MAX_SIZE 512
: T, }1 i9 R8 _9 I* R# j% \ - 4 W0 q5 @5 j3 f. Y. K
- int main(int argc, char **argv) + C h7 M5 A* e4 k8 v
- {
0 u! H, p# x3 n9 z$ f - if (argc != 2) 2 t4 _/ _+ N( q* x4 w" O( ?
- {
. z& T6 J4 v* [' E' s' \ - printf("Usage: ./%s ServerIPAddress\n", argv[0]); * r0 t/ q5 B. i1 l$ A) Z, L1 B
- exit(1); : R7 ~7 `' \9 X" w! i
- } 7 m. V; ]: W8 j& ?6 d- R$ @7 j
: `' P. z S `- H% G- // 设置一个socket地址结构client_addr, 代表客户机的internet地址和端口
5 |7 i q) e' X9 Z( r( n - struct sockaddr_in client_addr; & S9 y" U/ r% Z, {
- bzero(&client_addr, sizeof(client_addr));
; \& r- _4 K0 A) P j! Q7 U - client_addr.sin_family = AF_INET; // internet协议族
1 t1 X. S" w, Y+ o - client_addr.sin_addr.s_addr = htons(INADDR_ANY); // INADDR_ANY表示自动获取本机地址
- A$ M K& D' @ - client_addr.sin_port = htons(0); // auto allocated, 让系统自动分配一个空闲端口
3 b) F, q$ p0 g - . G4 H G7 O+ p) a
- // 创建用于internet的流协议(TCP)类型socket,用client_socket代表客户端socket
) d8 q8 Z2 U1 j6 B5 ~ - int client_socket = socket(AF_INET, SOCK_STREAM, 0);
: }% l- P6 J b2 ]0 J$ e8 } - if (client_socket < 0)
, M$ f+ T: l. s. B$ K2 B; B& x5 l - {
0 k! @: K+ h8 y: t. j; I( y - printf("Create Socket Failed!\n");
! m8 J- b8 [0 |4 H - exit(1);
0 l* y" I$ M! c& f - }
8 @8 B2 C, ]2 V0 A* }
6 g) r/ W3 V; [1 o- // 把客户端的socket和客户端的socket地址结构绑定 * J# v, ~0 J; p! G/ B" n6 y
- if (bind(client_socket, (struct sockaddr*)&client_addr, sizeof(client_addr)))
% Z# ~9 H( A6 P- Y) A$ \) y0 t0 S - { 4 ` k* @# }3 [9 E8 D: w1 j
- printf("Client Bind Port Failed!\n");
' i) w: o' _/ l - exit(1);
4 R6 T% O7 p. u9 C- z% H - }
3 B% X7 Y( }2 W1 A7 g4 Q1 M' d b
* u3 Q# y2 g6 }# E/ S' \/ Q& [! d- // 设置一个socket地址结构server_addr,代表服务器的internet地址和端口
" J: u$ v' {7 j - struct sockaddr_in server_addr;
2 a1 N! c% n1 x - bzero(&server_addr, sizeof(server_addr)); 8 M' C! |) ?1 q
- server_addr.sin_family = AF_INET;
- [ j8 C1 h) X# I: A" R - 7 f$ ]( d. ~6 {
- // 服务器的IP地址来自程序的参数 + x" f3 `" z i
- if (inet_aton(argv[1], &server_addr.sin_addr) == 0)
! s7 k1 L' w5 R7 Z! C! f - {
+ A5 K* b# ?/ }& Y: X; T, J - printf("Server IP Address Error!\n");
Z! U. a4 U" n0 ]* y - exit(1);
7 M+ K5 H% p' [) K( C Y4 G9 \% u$ F - } % h, O S& D2 { w: z- R
- - ?; Z0 l9 X9 {. P) \; L
- server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
# v3 X- ^: q% Q0 \$ |3 [+ R/ w - socklen_t server_addr_length = sizeof(server_addr);
* I H: ?; t; U2 [( w - : ^' | `- K; L1 _1 T, z
- // 向服务器发起连接请求,连接成功后client_socket代表客户端和服务器端的一个socket连接 & j, N. `' p% H* M
- if (connect(client_socket, (struct sockaddr*)&server_addr, server_addr_length) < 0) ) H' @1 K5 G0 T% u& U* `! |) q' A
- { % i [# _; S7 T% D! o% i
- printf("Can Not Connect To %s!\n", argv[1]);
6 `9 A( Y! S2 s - exit(1);
7 {# C* b2 x! x0 ~& P - } 2 s! W t/ P) q3 @8 V" f( K0 }
- ! O. Y0 }" I5 y. b
- char file_name[FILE_NAME_MAX_SIZE + 1];
# \/ v8 @) i- F3 c - bzero(file_name, sizeof(file_name)); f1 R- l; Q5 c' Y0 L/ m
- printf("Please Input File Name On Server.\t");
4 {# Y& i: G5 @ - scanf("%s", file_name);
( j7 K6 o! f9 D8 y7 M - 0 q, X& h3 h3 |
- char buffer[BUFFER_SIZE];
' l7 u+ Q/ \; X( q ~0 I/ X - bzero(buffer, sizeof(buffer)); * Z1 m2 O: y/ L# l
- strncpy(buffer, file_name, strlen(file_name) > BUFFER_SIZE ? BUFFER_SIZE : strlen(file_name)); 2 Q2 Y) c4 N- ^7 W6 R0 v- l9 q
- // 向服务器发送buffer中的数据,此时buffer中存放的是客户端需要接收的文件的名字
4 M! k8 u. N: r2 d- p/ U - send(client_socket, buffer, BUFFER_SIZE, 0);
; ~4 C X! v9 `/ W2 J( Z& i - 2 s1 F) R, u/ R
- FILE *fp = fopen(file_name, "w"); " I- T3 J; T7 q
- if (fp == NULL)
1 O3 `8 a" L7 L - { " A" S6 s8 W0 v$ B4 _' I" q! r
- printf("File:\t%s Can Not Open To Write!\n", file_name);
5 n& {/ `/ I# p. O. u - exit(1); / Q7 W7 m* e1 i/ ]
- }
$ r6 M% s0 }2 X- J1 W& ^: {; P - 6 l, B0 Z2 N2 M0 j* c0 X3 T! E0 ?$ b
- // 从服务器端接收数据到buffer中 5 }' ^1 m9 m, I0 c3 i4 k( d
- bzero(buffer, sizeof(buffer));
/ E5 F* m8 L9 Q5 x - int length = 0;
2 e1 h# } j2 V2 C" G( C+ V0 V5 v - while(length = recv(client_socket, buffer, BUFFER_SIZE, 0))
& J' O& @) r5 [: Q - { ( J+ `- E" h2 K: z; m
- if (length < 0)
- v/ v- Z* V; \/ f2 g; b9 J$ b - {
9 h! t6 g8 q, I r X0 v - printf("Recieve Data From Server %s Failed!\n", argv[1]); 7 t9 `# y2 B0 V2 ?8 p
- break; 4 L1 b0 P0 S9 y( {4 ?/ i. l
- } 3 u. I8 _ Z6 Z; U( _" T
: ~3 H4 j c% Y# y- B- int write_length = fwrite(buffer, sizeof(char), length, fp);
# d# w) `4 ?9 ^' S - if (write_length < length) - J0 F' R2 ~0 M$ c$ h
- { C' m' |: [0 Z8 ?# A# Q6 Y
- printf("File:\t%s Write Failed!\n", file_name);
- R; \* ^, ~* \4 M - break; 9 W+ c. `8 e$ q4 k7 M
- }
3 W' b5 W! l3 i; F3 v; e( w - bzero(buffer, BUFFER_SIZE); : ~& m. x- V1 j* L8 i
- }
' i& [- h; R; ~5 S3 K4 N3 X - 1 P' L- S* i- @3 f/ G
- printf("Recieve File:\t %s From Server[%s] Finished!\n", file_name, argv[1]); 0 p5 g, x# ^: I( P
" m( s; ~* \9 B1 ]; T8 e& P- // 传输完毕,关闭socket - _4 C! W' Y- s# x, L6 q, C
- fclose(fp); : o/ v- i" D- z/ Z; d. ? k
- close(client_socket);
$ t- c P: I5 @. b" Q9 l - return 0; 6 o& k4 L7 O0 i T9 N/ Q3 P
: J% c' c: {- f5 j- } 1 G+ l1 d7 H% g1 b; B4 x
0 z3 G+ ~* }! L q$ m
复制代码- /*server.c*/
1 W3 R. ?& ~! I - #include<netinet/in.h>
- M( n P1 a, Q4 ~ - #include<sys/types.h>& Z7 I5 Z6 p8 X" ]& f
- #include<sys/socket.h>" _% a O. x( {
- #include<stdio.h>
% c7 {) |1 A& u - #include<stdlib.h>
& ?, w) {; _! y: H- t - #include<string.h>' w4 p* F9 F; y! m' G! W
- ! d9 o1 o" X/ I7 q4 w+ V+ ~; S; x
- #define HELLO_WORLD_SERVER_PORT 6666 //端口号
" \7 {% e/ l" D3 w; t' t6 H - #define LENGTH_OF_LISTEN_QUEUE 200 |- _4 n" V" j* ^* S4 J
- #define BUFFER_SIZE 1024
: |0 E+ q# D0 `% M6 s - #define FILE_NAME_MAX_SIZE 512: Q" A& i- r o+ o" t
- ( z) S' ^7 }, w3 Q. q; k! \/ b
- int main(int argc, char **argv)
/ K" L5 ]% y0 C; q* D9 s - {2 p+ R, ^2 ^0 s n. U. K9 [; X
- // set socket's address information }/ w4 V# U, b6 B. o9 f
- // 设置一个socket地址结构server_addr,代表服务器internet的地址和端口
5 S* a p! w( C9 g4 x' O - struct sockaddr_in server_addr;
# w: D3 j3 B4 ~8 ^$ X. S" D8 U - bzero(&server_addr, sizeof(server_addr));1 h1 X& {- m O! j
- server_addr.sin_family = AF_INET;. z6 o8 r$ U% N9 U" Y8 z7 G' s
- server_addr.sin_addr.s_addr = htons(INADDR_ANY);* H: S0 T- l' Y, a2 j0 b
- server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);3 T% l6 p/ n/ c- ?" _5 D+ E' {
- + ?8 d3 a: f5 u$ I
- // create a stream socket
% B0 V* {4 \+ }: b - // 创建用于internet的流协议(TCP)socket,用server_socket代表服务器向客户端提供服务的接口" b& x- z& `# J: o
- int server_socket = socket(PF_INET, SOCK_STREAM, 0);% ]2 {4 z- X7 M5 L
- if (server_socket < 0)
2 b1 O) V) y3 d; J; U/ V - {
" P% R+ \) k" g' c - printf("Create Socket Failed!\n");% z4 F( N/ p) f
- exit(1);
, N9 g* |: m& l. z - }8 b9 r, J& @# T
- $ f) s9 F8 Y. R6 V8 a. Z
- // 把socket和socket地址结构绑定* ]8 p2 ~4 L" t$ H, q
- if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))
+ F8 n7 }, p; D# O( P) c - {
' v- k+ V- ~& ]8 l; } - printf("Server Bind Port: %d Failed!\n", HELLO_WORLD_SERVER_PORT);% `: J( H& b$ J( @3 B4 ]
- exit(1);
1 U/ r+ k! A. L% j5 v+ ? - }2 t" X/ d( W) B
- ! I+ P8 O% i: d- U+ S# l9 P
- // server_socket用于监听
' R# t; V% E: B7 j# C - if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))
?; _* \, K0 C7 m4 v - {: v& s8 f- u5 q& D: G y! o) e1 l
- printf("Server Listen Failed!\n");! Y6 W9 F* G% \
- exit(1);7 Y# _" e7 }9 l+ y
- }
: e& D4 \+ i1 T, w5 q) Y h
5 O: ]- r: D4 n' K( C- // 服务器端一直运行用以持续为客户端提供服务6 `% h' h0 A; t( \! m f# x+ e
- while(1)
. c0 y D9 ^# u% y - {
- @6 c& m, @4 j - // 定义客户端的socket地址结构client_addr,当收到来自客户端的请求后,调用accept
8 C0 K4 C8 |: M) j9 d A1 U; h - // 接受此请求,同时将client端的地址和端口等信息写入client_addr中2 ]0 [, N( T; y7 y. [. L: m
- struct sockaddr_in client_addr;
; W9 m6 V( r0 r& o8 g6 w - socklen_t length = sizeof(client_addr);
3 ? M& k' L. i7 F* ]* u
+ r1 h, Q2 T9 Q8 o- k# \) p- // 接受一个从client端到达server端的连接请求,将客户端的信息保存在client_addr中4 W% [* b9 G8 Q
- // 如果没有连接请求,则一直等待直到有连接请求为止,这是accept函数的特性,可以
& S( m( W' U5 f* p - // 用select()来实现超时检测$ B! D* Y( `* S0 E% f% k* e" E6 ?+ O2 ]
- // accpet返回一个新的socket,这个socket用来与此次连接到server的client进行通信0 Y# I9 k' |- {& Y' P( R( W# x5 O
- // 这里的new_server_socket代表了这个通信通道
9 s5 \* h+ w- R" j - int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);
/ C' g; b- Q8 M5 s9 r - if (new_server_socket < 0); w) t2 ]' j) r$ r( S
- {- I+ B0 @/ b9 e
- printf("Server Accept Failed!\n");* {/ ?: G! u# a' p8 @1 c
- break;
7 z5 R( u5 D7 ~) h9 o( u3 R6 Q& J - }
% l) c: R$ t/ K4 i
$ i' Q% Q9 z1 G# {+ P7 q: ?- char buffer[BUFFER_SIZE];
9 O+ X6 _# z6 b; ]2 q5 |6 @$ D - bzero(buffer, sizeof(buffer));
, r; ~% p' f/ {1 Q - length = recv(new_server_socket, buffer, BUFFER_SIZE, 0);
9 I1 b) K' ]! i+ v4 R2 z - if (length < 0)
/ C& r4 B/ K6 e" E4 R% R - { S! Q6 R5 l2 M9 r
- printf("Server Recieve Data Failed!\n");
% @* r. U; S: p Z - break;' t( a' g* j; s5 N- W+ z- [
- }( w6 K& T6 y; w6 m9 X! \7 |
- 1 l$ W) L: z* P: ~
- char file_name[FILE_NAME_MAX_SIZE + 1];. C: e( `9 D- e$ c* m
- bzero(file_name, sizeof(file_name));
5 T- X9 C7 P5 o' E8 T5 P - strncpy(file_name, buffer,( p' y# V+ Y T) V& X K
- strlen(buffer) > FILE_NAME_MAX_SIZE ? FILE_NAME_MAX_SIZE : strlen(buffer));
. |9 `+ b0 M: d2 r4 w - 8 Q1 p/ Y& `6 h0 g
- FILE *fp = fopen(file_name, "r");
- {; i' i% N9 u/ o - if (fp == NULL)
- t+ D& F; c0 d - {# ^' K, N! [( R* ?' b# v
- printf("File:\t%s Not Found!\n", file_name);
$ J- S" B/ M a8 ]& U( w% @ - }" W$ D# a5 f5 n# _9 P- g+ n/ e5 l/ y
- else% }* O. N+ m& B" A: d$ i$ D
- {+ ?2 R" ^4 k/ i% m* A
- bzero(buffer, BUFFER_SIZE);( Z2 Y2 q! l# g: d }" L- O3 [" U R
- int file_block_length = 0;
6 M" ~8 ], f7 Y7 h - while( (file_block_length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)# a: I1 f; ?8 T4 E, I1 f
- {1 [1 v( }. B- e4 z
- printf("file_block_length = %d\n", file_block_length);3 m' l& H, y- D3 `+ F
% n$ u+ k- q. H- M$ J& c; w H- // 发送buffer中的字符串到new_server_socket,实际上就是发送给客户端
% @$ h0 Z2 ^, y7 k - if (send(new_server_socket, buffer, file_block_length, 0) < 0)
1 Y( C2 m4 \; ~, B; { - {: Q5 l+ y& e. ^- S6 O( R8 ]- B
- printf("Send File:\t%s Failed!\n", file_name);! i9 E9 ~0 D x7 ]* \/ g
- break;* `! B' W" X V5 V0 f
- }: E% ~$ Q( u t; c
/ t8 a; B& ?+ p5 B' ?4 Q9 W: V3 [- bzero(buffer, sizeof(buffer));0 k( q; j5 [; O
- }/ o* ~/ K( S3 {9 P- J9 Z
- fclose(fp);
/ X9 m2 k9 \5 ?! p+ S4 s - printf("File:\t%s Transfer Finished!\n", file_name);+ W7 ]" _% ~, s) R. S
- }6 ~7 @8 u" b' `8 F( M: |" n
! ~) \; w/ Z) N j& W. K7 b- close(new_server_socket);: v; t2 Y$ Z9 _2 ~
- }
* n0 b- a3 N0 d - 7 q! x: B1 D. [$ q0 r% m- Y
- close(server_socket);
5 \& z8 [6 i5 _0 B. F/ u" X - 8 K# s! \4 c; R! x
- return 0;
5 V" P8 X/ @5 m- F - }
, z# c% x% {9 U/ V6 T4 x) \
9 q( k5 E3 n& b7 \
复制代码 - h; @ C% z- x' ^: N
' V- ?6 Q$ s$ l0 \; s5 ~
0 m( R7 K4 p0 j5 |9 j+ U& O7 j9 m' q9 A2 W& j. d4 X l
|
|