cncml手绘网
标题:
一个简单的C语言的socket服务器和客户端程序
[打印本页]
作者:
admin
时间:
2020-5-9 02:14
标题:
一个简单的C语言的socket服务器和客户端程序
程序很简单,windows环境下的,客户端和服务器程序都在本机运行,在客户端输入发送给服务器的字符串,服务器收到字符串后会打印出来,同时与"abc"比较,与"abc"相同就会返给客户端,输入的是正确的,不同会告诉客户端输入时错误的。
/ n2 r0 v6 y. D+ R
客户端程序:client.cpp
7 v. b) Z3 j. ^7 r# r0 M; J
#include <winsock2.h>
: p0 d. e% g+ D6 H: R) O) c
#include <stdio.h>
" n. e! A, I+ r) J p
#include <stdlib.h>
; S% c% x8 u; \# r" V8 y" q
/ T9 \3 u% m9 N! z
#define DEFAULT_PORT 5150
; z( `- K- R3 q1 o7 }" V
#define DEFAULT_BUFFER 2048
5 ` ~) U+ [1 a* b' A' e$ }5 `
9 C! r- i0 ^ v) s( T2 K/ m. {
char szServer[128],
8 @$ Q; z( P: b7 z/ W+ L5 h
szMessage[1024];
0 o* l5 m8 W- ~! n% Y! T
int iPort = DEFAULT_PORT;
y8 {" j; A, ?. K8 I
/ z8 c3 J5 a. Y# b9 G7 w/ I
int main()
( C( C5 D2 n0 Y3 G. G
{
) w1 f( X% Y. i' J! }! s
WSADATA wsd;
& x" ]8 C% W J9 }8 y! s) {
SOCKET sClient;
, `; {0 |; k. h5 Q) d! |" T
char szBuffer[DEFAULT_BUFFER];
0 ~# h# u6 O2 T6 D! _
int ret;
* O2 ?; {2 x1 x% C7 e
struct sockaddr_in server;
+ G; ^/ Y! j! _; b: D
struct hostent *host = NULL;
3 v) a& ?0 ^% d, ]' _' S1 Z
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
+ U+ i% H* a0 c4 A
{
6 t5 h _2 e/ [
printf("Failed to load Winsock library!\n");
7 }5 y+ P& l% ^* `, b! z
return 1;
. {# u G9 J) |' D
}
; A2 @' G6 z: h: j
printf("Enter a string to send to server:\n");
) Z: D" [- z. v
gets(szMessage);
; N' _* X0 [( D( m0 [
// Create the socket, and attempt to connect to the server
# g# x8 [; n; G- X
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
7 C5 O$ o( E& d( B/ q
if (sClient == INVALID_SOCKET)
4 [) `. c$ Y% a H& }
{
# q- C1 r# W2 z9 K1 }
printf("socket() failed: %d\n", WSAGetLastError());
. E2 q: a2 n# ], Q, H o5 j7 d
return 1;
0 `5 [- X7 ]9 e5 h
}
) G$ a/ L4 H+ ?9 i* i: }0 T
server.sin_family = AF_INET;
( Q0 {* ^1 i& f- T( @2 z$ ?
server.sin_port = htons(iPort);
1 O% g6 a, `% e+ ?
server.sin_addr.s_addr = inet_addr("127.0.0.1");
& i3 p! h7 U+ S# ^6 I* V
3 L/ ^! e! B0 O
if (connect(sClient, (struct sockaddr *)&server,
: E5 N4 K1 ^% m- J/ u
sizeof(server)) == SOCKET_ERROR)
) N9 o/ P* R' h% z$ t
{
7 ~4 P; [9 N' e# ?6 ^
printf("connect() failed: %d\n", WSAGetLastError());
+ Q! ^) q6 Q: l Q# ~4 ]
return 1;
! O5 v1 z ?. R- s) O1 E
}
* {; H# c$ V' |' S- _
// Send and receive data
0 |: J) i- w, E( u/ W3 r2 C
ret = send(sClient, szMessage, strlen(szMessage), 0);
1 V/ k7 a; W9 _ _/ {; a. m
if (ret == SOCKET_ERROR)
, E* S2 M( ~2 \. r
{
4 n7 W7 F& S3 w: k% L0 I; _
printf("send() failed: %d\n", WSAGetLastError());
m1 `) H0 g5 G' I
}
& D' t7 {& k8 [2 c( S5 g8 R
else{
0 ?9 ]2 `1 Z9 T a! A
printf("Send '%s' \n", szMessage);
7 F0 k/ K% C; r r
ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
/ @& q7 F1 g) J5 t! ]
if (ret == SOCKET_ERROR){
: F. f6 y. l+ s7 y1 n
printf("recv() failed: %d\n", WSAGetLastError());
; r) j" C6 Z2 M% ]; m! z
}
( e3 Z7 J+ P7 V4 G8 _( N5 ~2 Y; i
else{
M! Z# y K' i% f( \. [
szBuffer[ret] = '\0';
8 c: R7 j! X. q5 a
printf("RECV: '%s'\n",szBuffer);
9 R0 c, | Y! n, F8 w
}
" t) {/ Z4 c. D$ x3 X: D+ b
}
% K( {* _, w1 [0 @
closesocket(sClient);
7 B6 v8 ~) Z* F) P* J
9 K( t( d% z+ U9 i1 M
WSACleanup();
0 }1 k+ O* O- p5 m1 J
return 0;
* K& J: W' Y4 p7 Q; k+ i. p
}
复制代码
服务器程序:server.cpp
! I F6 x0 F3 [: ^
#include <winsock2.h>
5 n, w% q, s0 T O' u% m% |
#include <stdio.h>
) R% t: Q1 C9 }% y, a* O3 Q
#include <stdlib.h>
1 P& ~/ H0 c1 K) x: T8 U
2 Q8 Z2 i' v) ?, o) _+ f1 L. F
#define DEFAULT_PORT 5150
1 S; u/ n: J- x" l4 C& |
#define DEFAULT_BUFFER 4096
$ O/ F. _$ w% J6 |
5 A3 |/ E) v, D
int iPort = DEFAULT_PORT;
. j# }5 u8 M2 G0 ?
char szAddress[128];
" ?9 i. u* n }# r. r6 R! t& h
: u2 x3 J. T8 I% U. g6 [+ V- i2 ]
DWORD WINAPI ClientThread(LPVOID lpParam)
! G0 { s) U" G, g1 ~$ c: l
{
) Z+ T5 M, _; n' P1 |9 ?
SOCKET sock=(SOCKET)lpParam;
8 k n) {" Y; a% w! Q {3 T$ w2 x
char szBuff[DEFAULT_BUFFER];
- f6 ]) W1 W' i: |
int ret;
& T: ], I f' O
% y1 m6 f7 K: L) _/ E
while(1)
' a( O& I; w7 Y; s
{
! ~/ n H9 s1 K5 L) r# @6 x
ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
) E! V+ ]' o; O
if (ret == 0)
: T9 u8 s1 K+ n+ C4 M# Y) w
break;
" l6 W# Z1 K" o) S
else if (ret == SOCKET_ERROR)
$ }4 l! ?: L0 [, i; ]) N( U& L: ?
{
7 e( W' _& Q/ X) f% d% O/ d; o
printf("recv() failed: %d\n", WSAGetLastError());
+ N/ L$ [# a8 \3 f& Z
break;
: `8 K1 V" b! g1 |1 A( R- P
}
& W% p R9 L3 m: E8 b% ]% |7 ?
szBuff[ret] = '\0';
5 S: N3 j4 S4 p6 ~/ \* L
printf("RECV: '%s'\n", szBuff);
: m( ^$ g$ {$ E d0 l/ G
if(strcmp(szBuff,"abc")==0){
+ Q# L% k3 z+ I7 n, k7 J
memcpy(szBuff,"Send the correct string!",25);
) R8 }% H( A' t8 P* x
}
+ B, i6 `3 q- i' p0 }4 z- s4 O
else{
( e; h( r. l/ r/ c
memcpy(szBuff,"Send the wrong string!",23);
- Y9 t5 ^9 _ y2 A6 s
}
6 T) c$ }* B7 h6 v0 o- G. d
ret = send(sock, szBuff, strlen(szBuff), 0);
! e1 E6 u5 D0 s7 P# u# A* ~6 d9 i
if (ret == SOCKET_ERROR){
' Y2 j& ]* A% j& B* H$ W' d5 `
printf("send() failed: %d\n", WSAGetLastError());
! w- P2 u" ^+ e, D, C4 p, D0 G$ P
}
. b: X! Y6 |3 }! V
}
^% j: i) r; |* a; d9 D* }( q/ i
return 0;
9 x% S$ T' ]2 \ U0 @
}
6 k9 i- a# Z2 j8 D* K7 [7 Y
( w: m: k* b) S. @3 Y
int main()
( o, j: V% T y! D% u# @# @- }/ O
{
% y2 i* M0 y. s" l' C, A# s7 X7 h
WSADATA wsd;
7 V6 V" y" q8 }
SOCKET sListen,
5 k+ O4 t( n/ o' S# ~
sClient;
1 a2 o- B2 E) j, l+ v
int iAddrSize;
, i& u. Y) O' A" a
HANDLE hThread;
/ r/ J4 x# Q* d
DWORD dwThreadId;
" _* j( ^6 l/ N; l B0 ^
struct sockaddr_in local,
V7 F4 L/ \8 ~( K% k+ ?4 `
client;
* d3 \: `$ Y6 S3 d' J
, V; a2 v& Q3 Q
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
+ a4 n! Z5 v$ l% V3 y
{
* D1 m% t5 J; A% l- E) M
printf("Failed to load Winsock!\n");
p% d1 i# s) t' Z
return 1;
: f5 r8 |; C+ ?
}
- \; [1 F- f* }% [ q
// Create our listening socket
2 H- Y( u0 H" l4 e4 a: n
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
0 T! T7 `% O' Q3 E. `' X
if (sListen == SOCKET_ERROR)
: ?; F( R, _+ ?: }# R5 x
{
. P0 o5 X% X; o) ^7 K, _( A. l3 ~
printf("socket() failed: %d\n", WSAGetLastError());
6 T0 ]# c$ d2 u( W
return 1;
" Y+ C5 g, M* H1 F) q$ r0 A
}
0 a1 }1 L6 ?* A3 u1 Q
local.sin_addr.s_addr = htonl(INADDR_ANY);
q* ?( H- N. c/ {
local.sin_family = AF_INET;
K8 M& N3 }: l* ]# `4 T
local.sin_port = htons(iPort);
! x5 ^3 [2 t" H7 K" k+ U2 c
1 |* ^/ n0 o4 A, S
if (bind(sListen, (struct sockaddr *)&local,
: `8 U2 f/ a9 k `; ~1 |0 ]; |
sizeof(local)) == SOCKET_ERROR)
9 H. r7 M' L! o: J! U( b
{
- ?+ V _3 O2 c0 I+ [3 L
printf("bind() failed: %d\n", WSAGetLastError());
7 n$ j/ @1 m/ @6 ^2 w8 {' l8 h
return 1;
" x$ h8 R9 g/ Y' ~
}
6 Q) J; t* n( E) w
listen(sListen, 8);
4 e3 U, H( r3 K! i+ p
// In a continous loop, wait for incoming clients. Once one
' ^4 I" w$ L' n: b: v) M8 g
// is detected, create a thread and pass the handle off to it.
! E7 K$ \* E6 x9 d1 Q; K1 a
while (1)
7 q% W. h/ V3 E: D: ?7 V9 g
{
5 \% w I+ e( |* X. b! Q6 l+ y7 e
iAddrSize = sizeof(client);
) F& r* G8 s; Q" K( \
sClient = accept(sListen, (struct sockaddr *)&client,
+ ?9 D. ] I* r4 k; F! G
&iAddrSize);
8 u2 D0 j) A- L* P0 U& ~/ b
if (sClient == INVALID_SOCKET)
6 n4 D: M' Z( L% `; _
{
7 u% _' R7 I8 J
printf("accept() failed: %d\n", WSAGetLastError());
& O9 P. y( t( }" r, s8 T/ j8 I" w
break;
" o; i! m; H& F: B7 k7 g7 D2 b
}
0 K i2 R6 z5 {: n) M& g# V
printf("Accepted client: %s:%d\n",
% _( m2 p3 o& z
inet_ntoa(client.sin_addr), ntohs(client.sin_port));
7 b2 b' B# O8 H
3 p0 j& v0 R5 c+ @
hThread = CreateThread(NULL, 0, ClientThread,
( i; }0 [3 V" E
(LPVOID)sClient, 0, &dwThreadId);
& }" N" E$ J$ p5 x& Y
if (hThread == NULL)
3 s- u% g# P0 }# K) d5 G* F9 ~
{
! x$ c/ l' d# I6 b6 x
printf("CreateThread() failed: %d\n", GetLastError());
( W! X: m6 k5 y: {" \% _
break;
0 s( g1 V- d. g
}
k3 X( C$ W2 l; M, b* L
CloseHandle(hThread);
; _' F/ Q; \1 ?
}
0 I' d" `4 I/ R9 T3 |# U% N
closesocket(sListen);
% [$ D6 @. T* {* Q3 _9 w% Q; }$ i
3 y: H3 L3 b, ~4 z: E4 A3 ?
WSACleanup();
- p# ` q7 |& m( ]2 y. ]
return 0;
! j6 u. a: r T% C
}
复制代码
9 I) O; o, t/ g: J9 ^0 [, D+ {
7 m, ?! u# `5 m
# ^! y' R: y' m& s: d
; h0 S/ A8 @( \) Q, x
/ a" {& l0 e/ M
作者:
admin
时间:
2020-5-9 02:16
作为服务器,你要绑定【bind】到本地的IP地址上进行监听【listen】,但是你的机器上可能有多块网卡,也就有多个IP地址,这时候你要选择绑定在哪个IP上面,如果指定为INADDR_ANY,那么系统将绑定默认的网卡【即IP地址】。
; H3 M! @- g: m8 H3 L* X$ e
3 H. ~$ W% A8 _ ?+ D$ p
作为客户端,你要连接【connect】到远端的服务器,也是要指定远端服务器的(ip, port)对。
+ t g) c% J! ^( H" ~) W1 ^7 j
当然,在这种情况下,不可能将IP地址指定为INADDR_ANY,系统会疯掉的。
& B9 A* `4 L# a) D- m$ l, N
/ U- g/ N1 h u. D* }3 s
Server:
" \) v! [% s! `, \+ s
#include <winsock2.h>
3 i2 n0 n* L8 ?# R9 w* a" S
#pragma comment(lib, "WS2_32.lib")
, e4 j& P, U" O; x
& B4 l ^9 ~5 ~/ R. T
#include <stdio.h>
" z3 \2 S" z3 p! }0 @
void main()
4 T7 k2 q1 k/ V1 n( _5 g: O9 y- K7 u
{
# D* B7 v( y6 ]3 ~
WORD wVersionRequested;//版本号
& R! f/ C1 u# m
WSADATA wsaData;
* F/ t7 I& J8 _. m/ [9 n) d8 n+ B
int err;
0 n$ r' i3 H0 H | s" Y/ U0 ?# s
2 z' G! P' |, A1 T& N6 \; T
wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
2 q" u2 H' n# J2 z! N# B
//加载套接字库,如果失败返回
& [$ d1 ^: m/ y9 D. s
err = WSAStartup(wVersionRequested, &wsaData);
; v" a+ ?7 I" z8 F0 B
if (err != 0)
5 E0 l: N4 u$ A) @" d
{
' Z! i9 R( u% @
return;
, ]( l. I$ r7 E8 l7 C
}
+ o2 i) I' f! i' O
: Q8 t1 F$ C* K/ v- z/ v
//判断高低字节是不是2,如果不是2.2的版本则退出
7 ]! E% c2 u/ ~' V) s0 ]
if (LOBYTE(wsaData.wVersion) != 2 ||
! J7 M5 N. [4 P/ D7 n! S1 O: c5 H
9 d5 w& q1 h0 [6 y/ ]) J( U2 Y) c
HIBYTE(wsaData.wVersion) != 2)
. Y! J5 @; W" H* [
1 T+ i, u) L. F* ~5 E
{
/ y7 L9 w9 w6 h3 }. f. `( H" X6 x
return;
0 ]! C. g l) k. T2 S
}
# W, q, n% [# m: n, k$ E( W
0 D, H4 ~" l# C
//创建流式套接字,基于TCP(SOCK_STREAM)
) x5 W7 |. Q" o. B# E% g9 z
0 U6 K1 m b8 n" ~
SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);
: D9 e, z% V0 O8 \% p* {2 t
8 w6 H! D s8 [# r1 o& r
//Socket地址结构体的创建
' z2 J' E; Y" E- i
1 q+ Q# f* W' t e
SOCKADDR_IN addrSrv;
- Z" \- v: ]* _* z( F
- T1 @" s2 i9 J1 z' Q- _3 ^8 ]
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
* n& |2 r2 U. g" x y; _: \
addrSrv.sin_family = AF_INET;//指定地址簇
2 J' C0 J8 [1 E! O9 o. }6 @
addrSrv.sin_port = htons(6000);
# `5 h7 N! q4 s8 T2 e0 I8 z& E
//指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换
/ W7 N$ N: D2 X. ~6 [
3 L( m8 v4 p4 Z# ]6 `
//将套接字绑定到一个端口号和本地地址上
* Q3 D* u5 m0 B4 f: @; m& I( ~8 @- x
bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行
1 n0 Z" m) Z# Z$ ^ ^0 H
% Q& {9 R* G6 H1 o$ x* |. r: `
listen(socSrv, 5);
, v L- a" K' k* {" F3 ~0 S: e% r3 r
" v/ q" z, `% E, E
SOCKADDR_IN addrClient;//字义用来接收客户端Socket的结构体
0 ?; f( [" L; c1 a5 m* r! {
) ^0 a' x2 {/ c9 Z; x4 y$ E
int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof
4 a8 _8 R% `; r7 z+ u( o
2 ]' z& k4 H# A; k, v
//循环等待接受客户端发送请求
- p. `% T4 ~" R: w. E8 i' P
- D, [6 J, h) P% v7 @( h* s, c/ y
while (1)
, I$ ?* x2 @5 N
{
& D; Y+ C1 S2 \ a' y. g* B
//等待客户请求到来;当请求到来后,接受连接请求,
_* u! u/ Q1 T6 o
' {, s; o0 W/ M" G6 {
//返回一个新的对应于此次连接的套接字(accept)。
# s: i6 \ ?4 L3 Q( c* I. B
//此时程序在此发生阻塞
8 r" k' z* g) G' [# U! o+ I. c4 S
1 S$ ^: | A1 p Z6 U
SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len);
2 P6 X7 ~1 L9 p z8 J; z
6 m G( ^6 J0 M5 P9 w$ Y) B
char sendBuf[100];
( o0 p* x; N3 v" |" Z# ~
5 M1 x: L/ H o: k9 e" N# [* p
sprintf(sendBuf, "Welcome %s to JoyChou",
, Y) c0 I! O- W2 y
* r6 |4 a6 v' f
inet_ntoa(addrClient.sin_addr));//格式化输出
7 _8 S1 p7 v$ E3 x
( e$ u0 K$ z4 a& v1 M
//用返回的套接字和客户端进行通信
5 Y, @' T0 y/ d7 p k# `3 y
; x" i; Z% R- H0 k5 ]
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多发送一个字节
/ A+ ~+ L- G3 {- }* h/ Q
) Q m6 F E8 m9 m9 E, v
//接收数据
* j# C" V$ x/ _9 {( v
, Z. r1 p$ u' W' k; W9 |- ?7 q
char recvBuf[100];
; s0 o; b& ]$ J. ?
; ~! b0 }) D; g. P' B2 E' ~
recv(sockConn, recvBuf, 100, 0);
" o9 C) ^; h& X* ~7 C
! ?3 e4 O" U$ v* f! c9 u6 ]. S. |. a
printf("%s\n", recvBuf);
, x8 O% N: C/ h+ ?2 q9 X
closesocket(sockConn);
3 J5 Z0 [! @* X: l
+ a& p( _1 P; L
}
& ^1 y% y8 z. X3 u, f) O1 Y
}
$ a3 S5 E, \ [) v4 }
: [7 X$ R) z& M- c
" Q0 C5 A+ h) _. {! ]1 F2 _
Client:
o8 B+ h [) [
- V7 H! c4 K% C5 v# w
#include <winsock2.H>
8 |5 J: w2 U7 t7 _) H
#pragma comment(lib, "Ws2_32.lib")
% l/ k& Y7 I" s
#include <stdio.h>
* ?1 W+ x/ L6 F; b
#include <string.h>
6 S9 X5 l5 S3 @
1 i' D( m# Z8 V/ h( q, ?& W4 x9 L2 W8 N
void main()
. Y6 B$ y' E, f1 N: \) [( W. O
{
% D9 C$ g, r( A' o% M/ j |
WORD wVersionRequested;
K2 Y3 H t; }& R
WSADATA wsaData;
1 A% ~: k- t, p2 F/ m
int err;
9 m+ E3 v9 n; B/ l4 C1 C
3 Z) K# s! |; m6 E/ t% @
wVersionRequested = MAKEWORD( 2, 2 );
9 K' v1 t6 W4 U2 p3 X$ _
# E. b& E- ]# \' q
err = WSAStartup( wVersionRequested, &wsaData );
- {: q2 r, T/ R$ e1 U% x
if ( err != 0 ) {
( l% j5 [. O; V( n# x
4 g& i! P4 C4 s8 Q$ c4 T- q+ W0 S
return;
L9 [' B4 Z) L1 D4 e. c8 X) Z6 ~
}
" L& h3 X4 S$ {5 s W# v
0 l/ F- b1 n/ p
% [' d! y1 `; N" K# B
if ( LOBYTE( wsaData.wVersion ) != 2 ||
) S0 y- W+ C T# X( }; K k
HIBYTE( wsaData.wVersion ) != 2 )
1 D0 s$ ^" z# x2 B- C$ K
{
8 `4 o( ]: v9 M1 K
# n' S+ t3 i% t3 b1 Z
WSACleanup( );
9 V3 E' K: I& E, r! [4 q6 |
return;
9 m4 S% q6 L$ B: l5 g6 h
}
/ L% g3 _: R1 |9 ~
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0);
8 y7 N/ q5 V7 X g# H) P
SOCKADDR_IN addrSrv;
! F& a6 H6 o8 ~) y- S; [! {4 k
addrSrv.sin_family = AF_INET;
3 }# D, t) k- f0 o5 Z* j: S
addrSrv.sin_port = htons(6000);
5 ?: H) w0 t4 {/ a6 a3 m
addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");//服务器端的IP地址
" G# [$ s- t3 i- B3 Z# H; a9 I
* R" |' [0 f. b
connect(socketClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
2 e' d/ }' C( \* O( c+ o& H! U
char recvBuf[256];
# z9 @) v# E5 e2 q, x/ I
char sendBuf[] = "This is Joychou";
4 B. K7 v8 Q; t8 p5 e( \0 M$ O: ]. C3 M
recv(socketClient, recvBuf, 256, 0);
, C+ a, Q0 y" |$ k- S' E! E' Y
printf("%s\n", recvBuf);
. Y6 ~8 w9 ~! d' n
send(socketClient, sendBuf, strlen(sendBuf) + 1, 0);
1 f, M+ S- ` x: J& o
closesocket(socketClient);
7 M0 B/ i; y! a, R
WSACleanup();
4 ?( K- U3 _9 |" H1 t1 u0 J
( C Z, O6 s' E! d2 }
}
复制代码
$ B4 G( Y" {3 b6 Y' u2 u; K
B/ G) S6 y& V4 a
欢迎光临 cncml手绘网 (http://bbs.cncml.com/)
Powered by Discuz! X3.2