cncml手绘网
标题:
一个简单的C语言的socket服务器和客户端程序
[打印本页]
作者:
admin
时间:
2020-5-9 02:14
标题:
一个简单的C语言的socket服务器和客户端程序
程序很简单,windows环境下的,客户端和服务器程序都在本机运行,在客户端输入发送给服务器的字符串,服务器收到字符串后会打印出来,同时与"abc"比较,与"abc"相同就会返给客户端,输入的是正确的,不同会告诉客户端输入时错误的。
5 V! ~4 C4 U, H1 |5 D
客户端程序:client.cpp
7 ^+ I3 K2 p3 g
#include <winsock2.h>
. P& y/ O- _6 J
#include <stdio.h>
9 s \+ l( a8 c8 b: [9 @
#include <stdlib.h>
) Y6 f1 T! v# _
( Q r8 |' ?; h1 q, t: y
#define DEFAULT_PORT 5150
3 F c2 c* l) N$ a
#define DEFAULT_BUFFER 2048
! a$ l9 L9 t9 s/ m6 J
9 o/ d& n& [3 {! Z9 Y8 B$ T7 k
char szServer[128],
" N/ B0 F9 b# l4 E; z) g) q
szMessage[1024];
0 g; N- R3 U( L% H5 Z# t* Z
int iPort = DEFAULT_PORT;
# R* f( Z. @$ H1 M
' _: A" L) t* R. y5 a
int main()
: \8 j6 l0 I% j7 ~1 y% D6 i9 @
{
$ d H. D' V1 w, y
WSADATA wsd;
" _- h, m- @- p& z7 C- u8 N" V; C
SOCKET sClient;
% v& n8 v4 }$ p; c
char szBuffer[DEFAULT_BUFFER];
8 z; D( U' P4 C+ y, u
int ret;
6 v% g& ^7 L# C! `% ~" c6 L
struct sockaddr_in server;
& H: ^0 z$ x6 I3 Y/ U
struct hostent *host = NULL;
, J" m( T' @) r/ F" ?) m
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
& f% X% j" M. Q3 J
{
1 b+ } k* Z3 {1 {& ~# W- j
printf("Failed to load Winsock library!\n");
7 a4 o6 d5 t- Q! n( R
return 1;
) y/ a8 |, D) s' S, c8 y& c
}
1 g( `3 Q+ X* A4 o( v# Q7 C
printf("Enter a string to send to server:\n");
+ k# {0 \: f! D" n
gets(szMessage);
7 n. L F* v. w' y P
// Create the socket, and attempt to connect to the server
# E4 G; y3 n( I: J
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
& m. I, ~# m E
if (sClient == INVALID_SOCKET)
s/ g4 Z1 X/ U! ]* V$ R6 ]( ]
{
$ g0 {& ^; C+ F
printf("socket() failed: %d\n", WSAGetLastError());
* w! z- Y3 c7 n; |! y/ E
return 1;
! t! I' A- F2 z7 d. H' S3 V
}
^9 A& A1 U9 o5 p* a% O
server.sin_family = AF_INET;
. Y) v) k4 S( X
server.sin_port = htons(iPort);
; S8 h) N1 p* g* g5 t+ h
server.sin_addr.s_addr = inet_addr("127.0.0.1");
& r Y0 r5 k1 S$ Y# C9 }, H# m, X
1 G k* a8 K( n+ j) ^' Q) ]
if (connect(sClient, (struct sockaddr *)&server,
2 @) X3 d9 {9 ]
sizeof(server)) == SOCKET_ERROR)
: q/ V; }/ i, N4 q; J: S0 L/ C2 ?3 R
{
5 M9 m; R) d3 P: ]: n7 J0 B
printf("connect() failed: %d\n", WSAGetLastError());
. v7 q3 N; C& A+ a
return 1;
4 B. z) X9 J+ W
}
8 ]8 b6 i: r9 v% ]
// Send and receive data
' B0 q' V/ h% Z( K* M
ret = send(sClient, szMessage, strlen(szMessage), 0);
: I! y6 O4 O4 v l; L! v
if (ret == SOCKET_ERROR)
% \7 c( h1 n5 L" N4 X
{
! S2 w/ O! e% M/ L
printf("send() failed: %d\n", WSAGetLastError());
- L: H. d: R' Z" U) ]5 h
}
' F; h/ C; X+ q: B2 x' h
else{
# b' ]: o7 K6 c% Y' p6 F3 u) W
printf("Send '%s' \n", szMessage);
. I5 r p6 j, I# |# p w/ y8 e
ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
7 J9 Z% k$ P! {
if (ret == SOCKET_ERROR){
- G- k( p) J- n' V
printf("recv() failed: %d\n", WSAGetLastError());
: w7 @- D( f6 }0 K1 o6 B7 e( O
}
`& j% p; _; X/ v2 N" j7 [$ d/ F
else{
/ Q5 u" i$ S. r* R# g9 J
szBuffer[ret] = '\0';
3 w2 R; j1 Z+ m9 }' |2 v9 h
printf("RECV: '%s'\n",szBuffer);
4 s& ~; Y9 U' I$ d1 Z& ^
}
: g/ j4 v+ P% I- V, u9 D% y* P
}
3 I: M7 D2 g0 @- p! o" C8 X
closesocket(sClient);
" t& g0 Z% D& Q3 i% M; F
/ ?' e1 l2 S- c5 c( O6 d
WSACleanup();
# j" n; V# ~2 C! r$ S& M4 F: U
return 0;
8 R: @ S7 c, t. T6 V2 c: u" T
}
复制代码
服务器程序:server.cpp
% g7 S8 }9 j) y
#include <winsock2.h>
3 {+ K2 }" z" M* A$ f
#include <stdio.h>
6 @0 r7 e6 V8 ]
#include <stdlib.h>
1 ?4 P9 |& {$ x+ N# q9 C X
5 h( I) C1 f/ B5 O
#define DEFAULT_PORT 5150
3 o0 W# ^$ y6 \7 H6 T$ A% q# t; F) Z
#define DEFAULT_BUFFER 4096
3 O8 O$ v. M5 U& {: Q8 g8 O
' g, a) |5 h# _% Y
int iPort = DEFAULT_PORT;
, E4 [/ Q9 t( C5 ^ h! V. ]
char szAddress[128];
3 S, P) D, X' Y
: i C: _, W# ?, {2 P/ v
DWORD WINAPI ClientThread(LPVOID lpParam)
/ q+ O7 L) B2 W4 V( `7 e1 W
{
6 l& ~- v5 t* [( X3 u- N: a
SOCKET sock=(SOCKET)lpParam;
$ a1 E7 |8 ~1 p0 K: X
char szBuff[DEFAULT_BUFFER];
' Z) {' U$ x- ]8 g" a7 |7 ?3 H& Q
int ret;
) p( ~4 ]. ~0 Q' S. C
% S, j4 ]# b7 N; P$ {5 o( J
while(1)
' t: c% z# w! ?
{
P, l: ^6 }' Q% F) w& `! z
ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
3 A+ U( h, C8 V4 N
if (ret == 0)
( S/ C: h! K7 y# a$ G% S
break;
8 n0 }2 w* v& `$ P+ t
else if (ret == SOCKET_ERROR)
2 P, i$ q, j2 f' I* G
{
/ x! g8 V! { J2 d) B
printf("recv() failed: %d\n", WSAGetLastError());
8 O5 z- I$ `( }$ l5 p1 Y
break;
0 E2 t* Z! L/ U6 B$ S' B. [
}
7 M5 u; s9 Y, c8 B2 y: o
szBuff[ret] = '\0';
% M% R" [; m, ?# _
printf("RECV: '%s'\n", szBuff);
3 x1 [4 X( g9 D4 B: H. K
if(strcmp(szBuff,"abc")==0){
! v8 O$ I( h" Q; D& f7 P
memcpy(szBuff,"Send the correct string!",25);
f+ @3 U7 g/ V" T3 i
}
$ d7 G1 m- G7 ~& A4 v8 V7 v' b ?) m
else{
0 J3 T# O. F5 M* U
memcpy(szBuff,"Send the wrong string!",23);
# [+ K9 F n9 j0 ~
}
) R; P& x v4 w
ret = send(sock, szBuff, strlen(szBuff), 0);
- _# |) C5 T% e- c2 e
if (ret == SOCKET_ERROR){
, U: U( Z# f+ Q5 @0 f
printf("send() failed: %d\n", WSAGetLastError());
/ S6 t7 i0 N( f& l
}
6 i4 M* X" R1 l% Y0 M4 X( S
}
& R% B3 J$ R- v- {( u
return 0;
; h2 z$ Q% P g; R: O2 e9 G
}
' |/ j9 G6 l; {2 q$ a' G
. b& w, P+ j6 _$ [# @
int main()
4 R9 b# {7 O7 o* M8 l$ p/ M
{
+ m! d1 e9 K0 Q3 A* X/ M N. c0 h
WSADATA wsd;
( G) Q! [! C( H K- W- b9 j
SOCKET sListen,
2 a6 w1 s9 n7 f# }" w7 \, L
sClient;
% H- n# c) L% q) {! {5 j% H, f
int iAddrSize;
6 I# \6 h# \- n( ^. c; s* K% o
HANDLE hThread;
5 U L, n8 o, z; ^% x, O( y
DWORD dwThreadId;
9 [" B9 r9 Y9 {6 }$ x
struct sockaddr_in local,
3 T9 _8 l& N) y9 u/ I8 z2 d
client;
0 \; g1 r& _: i1 q# P b5 z
- F% j- R; l$ U ]
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
% ~* `/ `2 U; A( {" [
{
8 K- M6 o; ]0 M% {& T
printf("Failed to load Winsock!\n");
8 \$ [/ j6 y' c, K
return 1;
( L4 }+ v$ @6 O. r! Q( X
}
; ]/ N5 ?7 r6 X
// Create our listening socket
9 K6 v. s; l; ~7 i
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
$ r. r2 }. V* H' l1 Q. t5 O
if (sListen == SOCKET_ERROR)
6 J* H& }2 C( z8 m* y# ^5 Q
{
2 ~5 \: W5 Y7 b' w
printf("socket() failed: %d\n", WSAGetLastError());
# j J# z, p# o
return 1;
+ g/ x& w9 d. g
}
( f4 F1 t- O% Y I
local.sin_addr.s_addr = htonl(INADDR_ANY);
& d' L, t* l6 {# `. E
local.sin_family = AF_INET;
# K7 c# n9 e0 h3 E+ E
local.sin_port = htons(iPort);
' k0 s: `3 l4 ^! a9 ?
3 b9 U, e# x8 \: t( V& X! U
if (bind(sListen, (struct sockaddr *)&local,
* v6 s5 |; i4 f0 B
sizeof(local)) == SOCKET_ERROR)
) j# O) v# ~ U" q
{
) @/ i3 m8 [+ }+ v0 k4 i& r
printf("bind() failed: %d\n", WSAGetLastError());
# E1 O: S$ \+ `( q: N! t# [
return 1;
4 V# |% d% c6 J# b5 C
}
`# n$ [+ H) u' \: Z0 y" M
listen(sListen, 8);
. [/ o! M7 }/ d3 X
// In a continous loop, wait for incoming clients. Once one
; r8 a- m5 N+ v1 B8 {6 v4 G
// is detected, create a thread and pass the handle off to it.
4 C, {! j3 x/ S) v# \
while (1)
2 s% j' L$ P3 L3 d; a) D9 W
{
0 S) ` b& K2 g: `; O8 p7 } q
iAddrSize = sizeof(client);
2 E5 n, u: t+ m) S! z- e
sClient = accept(sListen, (struct sockaddr *)&client,
, X# u# P. \; i$ q
&iAddrSize);
. G; y. ]& x0 T: W- u0 D. O
if (sClient == INVALID_SOCKET)
! C4 }. `, `& [1 `
{
! W6 Q; T7 u) b [* B" Q3 e
printf("accept() failed: %d\n", WSAGetLastError());
9 E& v8 I$ `+ Z$ T
break;
; H! E0 V3 t% C7 V4 p7 E7 f' V1 j, L
}
% K" d2 _ G6 C& B4 A
printf("Accepted client: %s:%d\n",
, E1 h& P. F L. u/ t6 M1 ~3 K& c
inet_ntoa(client.sin_addr), ntohs(client.sin_port));
2 `; H; o* Z3 [* n' S; Y+ g& k
% e* F! S4 J+ t3 o' Q' q+ p
hThread = CreateThread(NULL, 0, ClientThread,
& J2 k& O3 _9 ^0 G+ r7 V; W
(LPVOID)sClient, 0, &dwThreadId);
+ w0 o' [+ l+ Z( z, _& O# W
if (hThread == NULL)
) F& M7 l( _5 I% ?! X1 y! |- W- s$ d
{
5 \" ]7 ~" }5 [0 e! Q7 n& }
printf("CreateThread() failed: %d\n", GetLastError());
K9 R: W5 S; P
break;
; X4 e2 R( [1 ^9 p/ [$ a6 @
}
+ h" U) U9 X4 P. ~7 t; g' C
CloseHandle(hThread);
0 L2 F) W# Q5 {$ @
}
1 {7 f1 Z4 ]5 s+ A0 R3 ]$ a0 F
closesocket(sListen);
$ I0 R$ {8 v. L( }7 R/ c) L
- q& F2 d( C, U8 O2 R9 H) d6 F; {
WSACleanup();
b: R ~8 ~+ m
return 0;
( Q! }" h4 G1 {1 M+ l4 t( _
}
复制代码
& |$ [( f( X. `' e. g: h( C
8 }; ^4 J d/ C* i
9 J) k; |7 O0 p1 _
h% a! {9 T& |5 O; E
' Y. a1 ?) Z. h8 p9 |* q. f+ `
作者:
admin
时间:
2020-5-9 02:16
作为服务器,你要绑定【bind】到本地的IP地址上进行监听【listen】,但是你的机器上可能有多块网卡,也就有多个IP地址,这时候你要选择绑定在哪个IP上面,如果指定为INADDR_ANY,那么系统将绑定默认的网卡【即IP地址】。
n" F! ?1 s8 L1 ?* @0 V3 W- b2 f
% ^0 i4 M: ]! o' j
作为客户端,你要连接【connect】到远端的服务器,也是要指定远端服务器的(ip, port)对。
& \. c p) g1 s! c4 x' D+ u9 l
当然,在这种情况下,不可能将IP地址指定为INADDR_ANY,系统会疯掉的。
; m" S; a* J9 T
9 M3 Y1 `; Y2 ~" _- a2 [! c
Server:
1 g4 u$ j5 o) s6 }8 |% }3 y
#include <winsock2.h>
! \+ @( T* I* r
#pragma comment(lib, "WS2_32.lib")
. q E* [. v. u) v1 x: R0 l$ J
8 w5 z8 c8 t0 b' b& `
#include <stdio.h>
% r0 w% }" d' @ h
void main()
: M* v" m* S' A4 Y$ v1 P5 L4 F) ?* N
{
9 h/ T m1 s8 U: ^, o9 e6 }
WORD wVersionRequested;//版本号
* A5 Q4 D. C: P, F
WSADATA wsaData;
* I) v; |) M; u5 {0 r
int err;
7 ^5 g H. s4 i' n; z* y5 F' \) [
( d _0 P3 [2 x5 ]: C8 ? t- S
wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
* Y3 q- j5 n) k
//加载套接字库,如果失败返回
4 Y+ m0 Y7 j. y; L
err = WSAStartup(wVersionRequested, &wsaData);
4 l1 _4 y, U' G. H9 z, ~) ^
if (err != 0)
3 G* q% T/ x k8 X" Q; `7 Z
{
) g1 P' }5 `5 y
return;
* x8 H1 U# N( s1 h5 n3 C( _7 n, W, v7 z
}
( U3 Z( O. Y+ V8 J
6 o1 z8 I8 `% f. g3 s# {
//判断高低字节是不是2,如果不是2.2的版本则退出
& B! H, V3 p* @3 X2 e# r7 U6 d, ^
if (LOBYTE(wsaData.wVersion) != 2 ||
( P0 n% N/ e. I3 `9 G2 O% V/ R* b
: A( [: Q+ m1 F7 q
HIBYTE(wsaData.wVersion) != 2)
0 X# E6 u) b" o' w& g0 m
0 N% J j- E) l" m/ A" O) N
{
- h' s7 Q: S( u; w. k( y
return;
/ m0 q; x5 V6 w- d
}
. t6 M7 D# w( q
/ d- f: P+ J7 Q8 @2 p4 |, o0 F' s
//创建流式套接字,基于TCP(SOCK_STREAM)
1 S' Z* l4 r7 m! I! a$ K- w; p% U1 k
) N5 U3 X9 ~! v( s+ p, q
SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);
4 V6 ~ p5 z$ F, f! x9 I3 \
8 _2 X. P a- d5 q9 @- T
//Socket地址结构体的创建
* h6 [7 h' O1 h0 e0 w
4 C. v- j( P6 M+ W1 o6 O. s
SOCKADDR_IN addrSrv;
* r8 T w. X6 w# H
8 j# s% [* x4 p6 z# w' g% J$ ]
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
' R c1 d) K2 J9 f* W
addrSrv.sin_family = AF_INET;//指定地址簇
/ Y' z# ~: ?* Z1 I) {4 ]
addrSrv.sin_port = htons(6000);
- Q8 \ C$ _2 r( A
//指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换
( |$ Q9 t1 W5 Z
3 u, q+ d. M0 R3 u- ~8 R. B
//将套接字绑定到一个端口号和本地地址上
) M3 `6 ^" U( _% `% A- T! {
bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行
+ _6 r1 r8 F) g4 \1 }' X
6 I8 h- f: i+ d( H" s$ U2 Q2 a ^0 N
listen(socSrv, 5);
b! J1 m4 l; t6 i; @( y
* Q" b. E% i1 c' F7 M; D
SOCKADDR_IN addrClient;//字义用来接收客户端Socket的结构体
. P9 x. F6 I& W, G8 C( g, L
6 J! ?* Y8 q0 @7 g% T4 J% s
int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof
/ |2 y T9 x5 W
: j! ?6 j3 H" l
//循环等待接受客户端发送请求
9 K3 L' J4 w. r
5 y. F$ s+ C6 D
while (1)
: B K" [# J% p! ~* U3 {
{
, F' U- V( E0 h, i1 ^5 T
//等待客户请求到来;当请求到来后,接受连接请求,
) s" F3 Y8 U: L G
( j: M4 C6 f+ a9 [- ^
//返回一个新的对应于此次连接的套接字(accept)。
. x R5 r8 U* M' C: p
//此时程序在此发生阻塞
/ q8 T( k& X' b. v/ W
! H+ p" ?( a& g/ T
SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len);
" U% G9 O4 Q. T4 G6 M! p( }( [2 o
@) N4 F3 M+ K. H9 w
char sendBuf[100];
k. q# G. {* i) F
+ l" F) \5 B( u5 z' G
sprintf(sendBuf, "Welcome %s to JoyChou",
! c' ?) k0 f% V' y& {2 p
+ X: c7 |4 x- A! S
inet_ntoa(addrClient.sin_addr));//格式化输出
3 ^, w& ]4 l' @) v5 u" @
6 K! S4 F! I; p2 W( D; r6 K2 V
//用返回的套接字和客户端进行通信
$ R! {4 {% ? S4 m: X6 ]
- V1 v$ X# c1 D, `/ D/ [
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多发送一个字节
8 W9 c0 e3 l j! a
# H' |* ^. e! _
//接收数据
6 @. h5 s; r9 r1 i9 x, \
# h/ V' Y; E/ i' c' S2 Y1 |7 P
char recvBuf[100];
! N2 Y4 G6 y+ M1 P; y! l
8 h0 w( @6 z1 H# [
recv(sockConn, recvBuf, 100, 0);
8 p9 i+ B6 V, h( ^. J
2 B/ \' T1 Y" ~% o
printf("%s\n", recvBuf);
/ j8 \8 Q% m- A0 l3 _( h7 s w
closesocket(sockConn);
3 L9 y" ?" o h$ q$ z* f
u: R0 P5 T1 G& M* \
}
9 c& \1 r+ S, H8 A
}
+ K: m* ^ g$ `
; ]1 e8 D+ s F l. a% V* ?2 J7 ` u
3 B. h) C& Y- H) V. m& Q
Client:
% A o5 l P; @* o
5 I# k6 N7 q! ]6 q
#include <winsock2.H>
/ f1 k* Y( _; ]5 j
#pragma comment(lib, "Ws2_32.lib")
) Y3 s+ R. y- n: L7 j
#include <stdio.h>
* L r4 t* H+ C# l& s0 g! {
#include <string.h>
& T7 O. p; M7 E: n/ h- d
. u8 q% j0 ^& k# a6 H8 {* A
void main()
, D; ~3 m1 x3 E+ m- W, U6 w0 U3 p
{
5 n2 r5 B( q7 H" P% Y- N8 P& e4 m
WORD wVersionRequested;
0 g& }& H/ {7 L' i/ I) H
WSADATA wsaData;
( E. _) p3 x M1 H# ^
int err;
, W; h7 n. Q {2 n# t
! U" C8 c" y- U, N4 l9 J# Z
wVersionRequested = MAKEWORD( 2, 2 );
7 Z- G g7 V5 d% ]
5 L! {: Z3 l8 a2 P
err = WSAStartup( wVersionRequested, &wsaData );
; O' h5 j6 E7 W/ f, W5 w
if ( err != 0 ) {
- J! j; ]% \0 [/ {* _
5 G, H' E( }0 B% S9 o4 W3 [1 L: G/ Q
return;
- O0 E& u0 A' U7 K( t
}
: Y* I) O8 s( ~- I. R7 g& k
3 v% C* z( F8 \" H& d
J0 I, K! \# w& F! C( v5 @
if ( LOBYTE( wsaData.wVersion ) != 2 ||
" |' ]# e0 i6 K8 ]" |
HIBYTE( wsaData.wVersion ) != 2 )
6 K6 q( Y0 e6 [. b+ O* d# Y! u5 h( D& T
{
6 D) q7 G) p2 ?( X, M9 t
" B; [. R* S8 t& [
WSACleanup( );
y* c G( n3 d* z5 D) n9 t" r( o( u
return;
9 n& W: l. q0 l0 U- |, m6 g1 V. m2 G5 ?
}
5 W" R. |$ Y; e& y# A+ a( Y$ D p
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0);
/ g* K x4 Y( ]# h' Z$ U
SOCKADDR_IN addrSrv;
& C! ^. i0 L( K& J3 B4 {7 N
addrSrv.sin_family = AF_INET;
" D7 g# p) j: M r
addrSrv.sin_port = htons(6000);
# t: Y& i0 r* K0 O
addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");//服务器端的IP地址
D! N6 X& @ f9 x1 G! @
1 l+ B5 t0 G+ d
connect(socketClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
1 l l# p% U% F; x Z0 J9 E& ~* }
char recvBuf[256];
2 p5 m% J5 ?* R7 h8 i/ A
char sendBuf[] = "This is Joychou";
! I7 ]2 ~+ f1 }3 l5 M; T7 p3 }( m
recv(socketClient, recvBuf, 256, 0);
' [! ?( G9 l/ x% c, f
printf("%s\n", recvBuf);
4 R8 R m3 D3 D$ x
send(socketClient, sendBuf, strlen(sendBuf) + 1, 0);
# B/ i5 J1 J8 V: m5 w' {
closesocket(socketClient);
n+ e; n9 _" x: s5 \
WSACleanup();
4 G) ]' A. R4 Y. O e
8 l( V5 P0 E% k+ ]. |+ e$ p b1 w2 U. Z
}
复制代码
2 Q4 G. x# F7 ^) ~/ n+ j9 b8 R, f4 J8 x
) }" Q6 j' k, E5 \ d" N+ p9 g5 y
欢迎光临 cncml手绘网 (http://bbs.cncml.com/)
Powered by Discuz! X3.2