cncml手绘网
标题:
一个简单的C语言的socket服务器和客户端程序
[打印本页]
作者:
admin
时间:
2020-5-9 02:14
标题:
一个简单的C语言的socket服务器和客户端程序
程序很简单,windows环境下的,客户端和服务器程序都在本机运行,在客户端输入发送给服务器的字符串,服务器收到字符串后会打印出来,同时与"abc"比较,与"abc"相同就会返给客户端,输入的是正确的,不同会告诉客户端输入时错误的。
- T- W" q% l% [1 }) B- k7 Z
客户端程序:client.cpp
, L, ~% G6 y9 Y; T# {6 y" N
#include <winsock2.h>
! X0 u9 z& U% o& J$ V
#include <stdio.h>
* X0 G) @, @# b) {4 X
#include <stdlib.h>
' m# {2 q3 m( l7 K: q
) g; g1 E. |; J, w
#define DEFAULT_PORT 5150
; T: ^4 Z3 W0 [( y8 p' \
#define DEFAULT_BUFFER 2048
. `" s7 |' a8 S
- L1 S2 r) U6 Q
char szServer[128],
2 j, j/ s- e$ H8 j) ~4 ^1 Q7 |
szMessage[1024];
, a; p( |7 b& q3 F- X& ]
int iPort = DEFAULT_PORT;
) { p! R+ i6 v1 T
m1 r, @) p5 `
int main()
# ?) Y3 G* T! k
{
2 U1 r7 A3 ~. W h% b
WSADATA wsd;
7 R6 Q# E$ J- z$ G6 m
SOCKET sClient;
8 C7 ~0 l8 T) W" i/ M. ]% F
char szBuffer[DEFAULT_BUFFER];
' ]7 X9 n6 N+ S0 ^0 N+ k- V
int ret;
2 A5 C% B5 c# q
struct sockaddr_in server;
9 l4 q3 o1 w1 F' k9 L! r4 d
struct hostent *host = NULL;
. ?6 U/ }+ G+ @3 r: `- ^2 D
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
/ p% c7 v3 z& u: }7 | M
{
- A5 Q' c: n; h- C* p1 r
printf("Failed to load Winsock library!\n");
1 u* f" N8 b! [% M0 [ u
return 1;
; Q9 z6 u6 r' @4 N
}
# |8 b$ a5 ~8 t U7 N' Z( `
printf("Enter a string to send to server:\n");
8 M1 Z' j4 R" A) y. l' \# g; Q1 @
gets(szMessage);
/ B6 |+ o7 \+ }) h3 I k8 G
// Create the socket, and attempt to connect to the server
+ E( H7 `6 u' n! l4 a! x
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
* E- g, z3 ~9 [" ^4 a
if (sClient == INVALID_SOCKET)
2 }# g! t1 z) j% {
{
4 N& l) X$ z& f5 E. Y
printf("socket() failed: %d\n", WSAGetLastError());
0 s, j# w0 m5 R8 ]4 L( q+ w( { d
return 1;
$ v: l; A7 G' N/ z/ y
}
: f, b3 ]/ ~! m6 j& p) P
server.sin_family = AF_INET;
! W, T2 ]3 M) t4 M3 b7 k/ u
server.sin_port = htons(iPort);
# ?; V/ n( k' i' l3 K
server.sin_addr.s_addr = inet_addr("127.0.0.1");
$ E4 H5 Q2 {2 H: H/ y5 ^
# i+ K& ^! ^6 _) c; z( V2 F
if (connect(sClient, (struct sockaddr *)&server,
: |4 o7 U$ m6 V6 l# B' z! U
sizeof(server)) == SOCKET_ERROR)
; C" h& z" {" q/ Q/ z; _, }
{
0 z% J! S2 d, C
printf("connect() failed: %d\n", WSAGetLastError());
; k4 G" V+ d a2 g
return 1;
5 Z: K& {+ u6 Y% E$ E* U
}
! K8 e: \, j) @. E) l3 k$ Q9 T
// Send and receive data
& Z* r0 B% v- }- T8 q9 @
ret = send(sClient, szMessage, strlen(szMessage), 0);
9 l9 M8 k5 B* H
if (ret == SOCKET_ERROR)
/ u1 D" ]) }4 |% x8 c+ J- Y3 s
{
) |7 k' s9 t9 W3 c& b* d
printf("send() failed: %d\n", WSAGetLastError());
; ~7 C7 \$ t+ n4 T& {
}
$ X' a6 r6 _6 R
else{
4 ]+ D0 G! G9 ?0 } ^
printf("Send '%s' \n", szMessage);
% X$ |% f( x2 h8 k
ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
" @" O5 c9 c/ G) W1 v) P
if (ret == SOCKET_ERROR){
; ?. ~3 T( h! p0 {
printf("recv() failed: %d\n", WSAGetLastError());
. S+ y8 {# j- @. r* v7 j1 n
}
7 M O. n" Z d7 c
else{
: m# y+ s0 _% D* m' d+ Q) J
szBuffer[ret] = '\0';
+ E: P1 q) B# c `2 w$ R1 c& I6 J+ Z
printf("RECV: '%s'\n",szBuffer);
) z7 ]& j/ h5 A0 E0 P" _
}
! w8 C: |* F9 W: F4 a+ l
}
3 i* ?4 d( P: @. c6 ]- N# _0 p
closesocket(sClient);
0 d# k7 \* W) l) ]* Y7 J/ Y
$ ]5 \. T) z% u$ A) E9 E/ v5 G9 C
WSACleanup();
* A- E/ |3 X7 G; L9 Z8 }
return 0;
! |0 m" C1 s+ C; s) u& u
}
复制代码
服务器程序:server.cpp
" R, A- P, e, Y4 n' s5 m2 M! d
#include <winsock2.h>
5 r# V8 r$ Q2 d/ v9 h2 B
#include <stdio.h>
1 l. X' C! y( E" }( ~
#include <stdlib.h>
1 U. b3 c# d- x6 w- [( X& c
' k. R* H, F5 x' ^# M6 C
#define DEFAULT_PORT 5150
8 T2 Y0 s& y2 f
#define DEFAULT_BUFFER 4096
/ Q2 \' ^6 C' H4 H Y" G9 K2 } G
( O, N3 D/ O, p5 q; U2 H& s
int iPort = DEFAULT_PORT;
, w- T9 V+ Q3 N4 H; b
char szAddress[128];
+ t' H9 q3 C# V' Z/ d A A& b" [
* g; T! |+ |. R- {
DWORD WINAPI ClientThread(LPVOID lpParam)
$ @2 e7 B X, j) J; x8 K; C
{
6 t- ]1 d( {8 T" |
SOCKET sock=(SOCKET)lpParam;
+ h, f1 ~0 j% ?5 z% ^% e1 X7 x
char szBuff[DEFAULT_BUFFER];
6 N0 x) x6 p0 }1 ~7 S6 B
int ret;
0 f) @8 R& b7 C$ {
2 }" f- R' U Q
while(1)
4 c% F9 I, z1 P& f5 L) i
{
% T7 p) j: ]& T& E6 L
ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
! p) w' e6 W. B" ^/ b/ g
if (ret == 0)
- ^2 Q: l. V n
break;
3 _6 I, z* x# P+ N3 \+ f
else if (ret == SOCKET_ERROR)
6 L2 t4 G! ^6 J. Y4 x, ?
{
3 z9 y: N6 v' N# Z1 Q6 b
printf("recv() failed: %d\n", WSAGetLastError());
# t; e5 \1 Z- L. }. p
break;
4 B! R( G: E# E7 x, [- v8 \: {! v
}
* ~7 @5 M5 ?# K& l% x- [" r
szBuff[ret] = '\0';
3 B3 L0 s. c0 m4 ?
printf("RECV: '%s'\n", szBuff);
8 C9 o, p) }& u1 Y" V
if(strcmp(szBuff,"abc")==0){
) f% V; D1 H; H2 d" S
memcpy(szBuff,"Send the correct string!",25);
- J6 S& _" p1 Q& v2 Y
}
1 E/ r5 k2 \) C0 h8 p% K: K& S1 i; c
else{
8 g, p# Y) P! P7 K/ k
memcpy(szBuff,"Send the wrong string!",23);
7 K8 V6 c+ C% [1 x2 I7 g4 j% m5 R
}
! n: B' c& R0 K9 D- ]! F: c! @& d
ret = send(sock, szBuff, strlen(szBuff), 0);
, ?! Z' u+ ]9 h5 M2 B4 P
if (ret == SOCKET_ERROR){
) J- J2 e" J7 |' ^1 `. h- K7 R' n: D
printf("send() failed: %d\n", WSAGetLastError());
$ c+ N% o- X& E" s1 e. `
}
. C8 ~8 X6 N1 F& u0 b* Y. ?
}
9 M9 h' F6 h7 Q( k
return 0;
3 m z. }6 E- {
}
4 S. T9 r# h; E0 B
# d: M0 B" @8 \9 X
int main()
* `, ^2 a* l8 ^4 R
{
: t2 R2 N N: |1 L+ P, L$ U/ P
WSADATA wsd;
! D* Q' `( z% m2 Z" U
SOCKET sListen,
8 Y0 J, H3 a( r. v
sClient;
( U V8 D" X2 w; R0 V$ y9 }9 e
int iAddrSize;
3 I+ W/ a3 c0 o) e
HANDLE hThread;
' R z/ {5 v9 r5 C' N& l9 i
DWORD dwThreadId;
$ p& l9 H9 c6 z
struct sockaddr_in local,
5 L* E: {: U& \/ B% b
client;
( \2 E9 p. a0 o: p& p% [: O0 y
4 w' x2 Q: V2 ^* l
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
* u d. |; b; a& b0 s, p+ S1 b2 m
{
- C' l* s# G9 p4 ]; I
printf("Failed to load Winsock!\n");
5 v" |! H! r q" I
return 1;
& u6 F, b/ t7 {. T9 ?
}
6 ^. Z( Y: b! y. Y# V- A# `5 q/ w4 X
// Create our listening socket
; {3 ?: ?: v- u1 M' i8 |
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
; R+ U q; t* `* J; L4 e( J* o u
if (sListen == SOCKET_ERROR)
8 G7 B( t6 h |
{
( e% t& C2 m' \! L
printf("socket() failed: %d\n", WSAGetLastError());
1 }. K" d! s2 j+ w8 W: b
return 1;
3 o$ L8 @ J5 |" b7 u4 ?
}
* ~4 H3 S. m7 A# v" n
local.sin_addr.s_addr = htonl(INADDR_ANY);
* F; }4 r% X6 N. ?/ C
local.sin_family = AF_INET;
D, h9 P) t0 P ?# o& Z0 F
local.sin_port = htons(iPort);
9 Z3 o- {% E% T% }1 J$ I+ g
: h# o# ^7 K! [) q+ p9 i
if (bind(sListen, (struct sockaddr *)&local,
. C$ R+ P0 d6 M6 x1 V4 n& h2 [
sizeof(local)) == SOCKET_ERROR)
/ F$ m) ?. i6 Z2 }! J' `4 a
{
3 ^0 ?6 A! s. d. V
printf("bind() failed: %d\n", WSAGetLastError());
1 V: [7 I& }# e, W4 T# o% @
return 1;
4 p8 c X" d7 }7 m$ j. E
}
) }2 W) V) K0 N7 [, y
listen(sListen, 8);
1 X+ c( _( Z& G' U8 I- t8 K
// In a continous loop, wait for incoming clients. Once one
( F; Y7 ~ L- t e
// is detected, create a thread and pass the handle off to it.
/ y# v3 g! a2 R' H
while (1)
! q4 X5 h& R* \- v
{
2 G9 P8 o- ~2 ~1 G6 N
iAddrSize = sizeof(client);
* K3 K3 }) b7 j y% E( G. K, W0 q" ^
sClient = accept(sListen, (struct sockaddr *)&client,
* {0 _ n$ r. [9 n) X
&iAddrSize);
0 t" F. T8 z! e
if (sClient == INVALID_SOCKET)
; { m {! b9 o
{
" F) o! _- l' u, Q: N8 s" F
printf("accept() failed: %d\n", WSAGetLastError());
! u' Y2 V+ i1 L0 G/ Z. x$ R$ x
break;
5 `8 G3 b: `' @* f' j+ V
}
; ?' ^5 O+ B7 k! D
printf("Accepted client: %s:%d\n",
* C, n. \9 x, B( \3 [8 Z$ m0 X
inet_ntoa(client.sin_addr), ntohs(client.sin_port));
4 ~, u: s8 f2 S7 @1 m$ U+ t
+ f7 H1 N* |/ y% o" L8 } ?' o' b
hThread = CreateThread(NULL, 0, ClientThread,
# p, T5 c( D* v+ ?
(LPVOID)sClient, 0, &dwThreadId);
f. Z7 o7 k0 Y) N: g, \
if (hThread == NULL)
" s7 d& J' M" ]9 x8 g
{
' _2 D7 O2 }. k6 D$ w
printf("CreateThread() failed: %d\n", GetLastError());
. Q) i; |. M( w. m
break;
. w! I. M# K" V5 @2 S3 m/ j
}
2 V. q) f* o/ j8 s
CloseHandle(hThread);
& A' }1 w6 z X6 ]0 M( k# q K2 k
}
& ?- z2 s# {1 X4 r9 v
closesocket(sListen);
2 b1 {& |+ Q4 B* Q4 @5 m* s
7 T# O1 q9 U3 x F- K8 @0 ~5 K
WSACleanup();
: @" g( R* h) T* C! o% q0 o9 {% k
return 0;
. T4 ^5 G. z8 L) ~4 H* u; }
}
复制代码
% `2 F- y* h2 Y+ k+ ~
4 `7 [+ } b. M1 b3 G
8 ^, i4 z: }* N- N9 ]4 E+ e
* _" q& t9 u. g5 n7 D$ ?% h) ]& C
" r% o/ F9 R, a* h) P
作者:
admin
时间:
2020-5-9 02:16
作为服务器,你要绑定【bind】到本地的IP地址上进行监听【listen】,但是你的机器上可能有多块网卡,也就有多个IP地址,这时候你要选择绑定在哪个IP上面,如果指定为INADDR_ANY,那么系统将绑定默认的网卡【即IP地址】。
e+ {( D; P: Z. `. K
4 _& u0 J- z: \/ d# Q. T
作为客户端,你要连接【connect】到远端的服务器,也是要指定远端服务器的(ip, port)对。
" [: l2 K" O! B! a+ r$ T
当然,在这种情况下,不可能将IP地址指定为INADDR_ANY,系统会疯掉的。
+ P# A, J' O- N9 j* }3 R2 t! I! M
% n d& p* L2 o u4 p! H: I u) _
Server:
/ ^) C, R1 L/ |5 `% U4 b
#include <winsock2.h>
: I* @" i2 {) v" L
#pragma comment(lib, "WS2_32.lib")
! A1 K; r- D# h% k& Z `$ _
* o3 X$ C0 L8 i$ f
#include <stdio.h>
; |& z9 }; s/ L' e
void main()
( e0 Z9 L, w6 R" H' m* t0 y
{
7 i1 A4 t& [* G* e" B8 k* ~
WORD wVersionRequested;//版本号
- H+ I I" Y) K" ^
WSADATA wsaData;
" S0 O* r( Q8 d- o4 P6 A
int err;
) T4 \; v( l/ ?
) s9 z6 {4 x8 m* R
wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
/ a" J5 v8 s: ?
//加载套接字库,如果失败返回
+ m/ }- w8 T+ {6 q- g9 ^" A
err = WSAStartup(wVersionRequested, &wsaData);
: F$ ^7 `% Z. o/ v8 c* X# v
if (err != 0)
& C$ v+ P/ J3 L! _- D$ B* P: \7 s$ R& C
{
8 d5 \" H2 ^7 r! A
return;
7 k2 F: a& i- u. h9 _
}
4 w+ F& M) y' ? u$ I4 u
- B( `+ y3 e* L- O6 x
//判断高低字节是不是2,如果不是2.2的版本则退出
9 a/ O( o& P# e. F
if (LOBYTE(wsaData.wVersion) != 2 ||
/ ?7 R8 t9 I8 v \2 l: Q
3 g0 {; M0 e- n/ [' M
HIBYTE(wsaData.wVersion) != 2)
; j/ \9 o3 y9 M, M
' Q* a A$ |1 _& u
{
) n: c! b- N$ s7 C2 L2 L
return;
8 ?4 Z0 [0 s3 q" W. F" s! L
}
/ u; `, g% K; l A- E' y
! R0 Z |( d& }* G+ a$ c9 W7 N
//创建流式套接字,基于TCP(SOCK_STREAM)
: a5 F/ H7 o0 k& }% P: F f
5 E6 \; v9 ?/ D k' H8 c
SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);
; O% E4 M3 I( x* S/ W7 ^$ A
& o& j5 W* n- T5 S: c
//Socket地址结构体的创建
: A! o) f. l7 p" W O& z0 ?0 V
" x- l) q: n* S0 e& L1 }! g/ O
SOCKADDR_IN addrSrv;
* z: {+ i5 {, m- ?6 w
3 Q5 C9 M" M9 g' G: {1 j* X5 X) V
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
- m5 C, ^( G0 {) E4 c# ^7 P
addrSrv.sin_family = AF_INET;//指定地址簇
( b3 F1 c6 t5 d S) a+ `" R4 t
addrSrv.sin_port = htons(6000);
0 I4 T( v; \. @2 R4 j: L% b
//指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换
u( v J9 ]( D" l4 l6 ~
, T$ B9 P, O, N2 l- P8 o
//将套接字绑定到一个端口号和本地地址上
9 A" W/ y v' g/ v4 q
bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行
+ Q- Q. d* f r d0 b
0 A+ e, k1 C. N6 [
listen(socSrv, 5);
5 w: K" `* O v6 B5 P- O
9 n# F* K* ~. R1 A. V2 d; K1 l2 o0 ^
SOCKADDR_IN addrClient;//字义用来接收客户端Socket的结构体
/ N! c. W' P0 q
8 o1 e. L3 P8 E
int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof
; o s$ \, R) f
1 T8 d" @1 K* o5 e; |! o
//循环等待接受客户端发送请求
7 z; E! [" n1 t( A2 y4 }" S# Z. V8 j
0 F! G, B4 b0 w2 E
while (1)
* n( g' X5 ?8 |1 R
{
3 V8 x! S% u; N1 F$ H" r; U4 `7 ]6 l
//等待客户请求到来;当请求到来后,接受连接请求,
5 F i$ X" P7 Z- ~' T8 [0 W0 |; B: g
1 L2 |6 A% R8 |: w
//返回一个新的对应于此次连接的套接字(accept)。
R! o- M# S* A w, y" M1 d
//此时程序在此发生阻塞
7 l! Q0 u! h; u& N0 _
7 o L7 X1 s+ z9 I' p2 @! q
SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len);
: A1 w5 Q- }9 g: J& O7 t4 k8 w
4 d# i$ G7 G% H! B% t/ }7 ^$ I
char sendBuf[100];
2 h! `& V/ w9 a
# v' d! S7 L: f& O5 Q0 _1 m) R
sprintf(sendBuf, "Welcome %s to JoyChou",
% r. h9 w3 d& R H1 `
- l& P; {) {) j
inet_ntoa(addrClient.sin_addr));//格式化输出
3 H. x7 m; l4 y) I: x
3 f" u& X2 M0 m
//用返回的套接字和客户端进行通信
+ T* e9 v1 A( `( s8 H, j1 ?# O2 ^
! m/ C) L! x7 ^ D
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多发送一个字节
8 a# ]4 D4 O& ]; }- A
) M' H, ]% b! X
//接收数据
8 y5 u! I" n# _
; s) X& l9 G- t. W" j2 c
char recvBuf[100];
% p0 f; h E8 r/ b7 N
3 ? P5 }# Q" V1 t9 G' @' d
recv(sockConn, recvBuf, 100, 0);
) O* E, ?3 E% B' ]+ T8 a' l
" O- V* H7 Y/ A8 L; N. ^4 z
printf("%s\n", recvBuf);
. g7 G! l( U7 X- N7 C( d8 m. l
closesocket(sockConn);
, W# b. w( j" Y. `
* ^5 {& b$ i/ J2 R! n9 K" H
}
7 m. g4 {* d. ]
}
* l: n+ y8 }! x, j
' i0 K0 N0 Q% \, o$ e7 U& c1 I
( }6 Y$ @# s6 p" i/ L$ @! d8 y1 N
Client:
& P/ }5 g$ a; l$ V0 c- I
) s5 m( |; Z0 m, J( M$ D
#include <winsock2.H>
& o: |, M0 n* [+ p
#pragma comment(lib, "Ws2_32.lib")
/ j% s$ V3 x/ _6 c: }" r$ O
#include <stdio.h>
. o+ A& B; R: S5 W& q. t
#include <string.h>
- C3 ^' h; _3 I3 m, T/ k; W* v
; D) |! i# X" L% w2 \1 ?
void main()
7 S3 n( y/ `6 o( `7 M
{
* s [8 u- R% v' _$ i
WORD wVersionRequested;
: w4 b3 U4 ^' X, v2 O, E2 H) i1 w U
WSADATA wsaData;
8 r+ H" v \! h* _$ {9 {( a
int err;
9 V- ^) `4 c. A e ~) d
, f) C! c e/ \& T. f2 G" E
wVersionRequested = MAKEWORD( 2, 2 );
; m7 S& [9 T4 M; I
* o! z8 {# i2 I. j6 \8 u) k
err = WSAStartup( wVersionRequested, &wsaData );
( w0 H& J9 T s9 f1 L: ~1 x
if ( err != 0 ) {
7 E0 {; X# U. v% T: v
8 i% t- a I9 r8 t
return;
" N$ }' X$ e5 P" X: Z2 i" w( D* x
}
, x) r! e- s. l
; h# V1 W4 o. J5 C" H3 X
1 G( A9 f4 g/ m: s
if ( LOBYTE( wsaData.wVersion ) != 2 ||
3 q2 T# x& x1 i1 M* _4 w
HIBYTE( wsaData.wVersion ) != 2 )
5 W; c! ]# ?+ O4 J. G5 A1 I! U9 o( f
{
s5 o- e& c. b9 F' i9 i1 S; F" w
9 H: | V3 G. O$ \
WSACleanup( );
?" q0 r4 k+ f" X
return;
b% ]7 [1 h' V+ V9 i' X
}
* L) [0 G! H& g+ }$ @+ h6 r
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0);
0 j/ z8 X, J' Q
SOCKADDR_IN addrSrv;
$ g$ ]9 X8 J6 R7 Q9 s
addrSrv.sin_family = AF_INET;
9 D3 } h& [& }% L0 h. i2 X
addrSrv.sin_port = htons(6000);
2 G( a: W" x, P6 R j0 D5 f
addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");//服务器端的IP地址
) t3 Q9 i+ f$ ?$ d3 W# R/ {
2 c8 v' ^$ ^! s4 ~! c q
connect(socketClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
) E% K" N& m- {% D6 C# O
char recvBuf[256];
I7 h, p/ \& f. W0 X
char sendBuf[] = "This is Joychou";
! I4 X+ @0 G/ x
recv(socketClient, recvBuf, 256, 0);
7 }0 V- r5 y/ r6 I6 i$ |& Y2 f
printf("%s\n", recvBuf);
9 G, g X$ w P: H) X) p
send(socketClient, sendBuf, strlen(sendBuf) + 1, 0);
2 Q/ j0 }5 H+ K- P( `) I
closesocket(socketClient);
8 ?0 a- t; {. M1 \
WSACleanup();
9 D' i& g" _/ W/ k: H5 k* Y2 q. Q/ `# v
% Z" [7 ?7 L9 M& |1 k; R
}
复制代码
& N. w5 [8 H) I
# h5 C& p& [% Y; L" q
欢迎光临 cncml手绘网 (http://www.cncml.com/)
Powered by Discuz! X3.2