cncml手绘网
标题:
一个简单的C语言的socket服务器和客户端程序
[打印本页]
作者:
admin
时间:
2020-5-9 02:14
标题:
一个简单的C语言的socket服务器和客户端程序
程序很简单,windows环境下的,客户端和服务器程序都在本机运行,在客户端输入发送给服务器的字符串,服务器收到字符串后会打印出来,同时与"abc"比较,与"abc"相同就会返给客户端,输入的是正确的,不同会告诉客户端输入时错误的。
' R3 A" i+ ^9 @, d8 M) {" X. c
客户端程序:client.cpp
5 X, I: c1 U- |& o
#include <winsock2.h>
: ? e' y4 D9 R ?9 u
#include <stdio.h>
- u+ o: M( x3 K0 i0 Q! I
#include <stdlib.h>
% ~: ?. M: j4 P; u6 Q
2 F* ]( K1 n' X0 T( V
#define DEFAULT_PORT 5150
* J/ D( r# C2 {) X* ~- r5 k7 p J
#define DEFAULT_BUFFER 2048
1 i% A3 Q$ `& Q/ r2 c+ f9 A" ]+ K" _7 Z
g! ~8 g+ I6 G7 ?
char szServer[128],
3 D4 u8 C% m8 s( E @- N+ D. ~
szMessage[1024];
: e+ M4 q& @1 H. f) Z+ j
int iPort = DEFAULT_PORT;
: M3 a1 j7 Z* y/ e. m2 ^
: q1 t( W2 M3 a3 w; s* e3 \6 i) m% c
int main()
, {: F# t5 e" F# p4 @, Z, j
{
4 ?5 q! T P6 h( \3 Q0 S
WSADATA wsd;
7 D. _; X# K. U/ L8 M+ s0 g" \7 M. e& B
SOCKET sClient;
/ R# y( {" S) q0 a+ M# J x
char szBuffer[DEFAULT_BUFFER];
2 f% C1 U; }% v/ P& o. X9 s1 H
int ret;
, J- N& w. u* h7 z# o9 I+ Q. h( R
struct sockaddr_in server;
# u: {0 S( {/ s5 i1 Y1 e A
struct hostent *host = NULL;
/ z* \( S. v, F' }3 Y
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
* r3 @/ r# R: G9 G
{
) F! a# N% `! O* g0 }! p
printf("Failed to load Winsock library!\n");
# |1 ]# q2 p0 ?$ U
return 1;
" }# |5 B& F. ?* k) `
}
$ z* O- b' d: O& l0 b
printf("Enter a string to send to server:\n");
% p m( n- \. D0 Z
gets(szMessage);
h* b: B9 C. F9 k
// Create the socket, and attempt to connect to the server
6 m: v3 V4 M2 B+ F
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
, w' ?( R2 I+ x/ x E
if (sClient == INVALID_SOCKET)
+ {& X! L6 D' H9 P0 q
{
3 g; q. H3 g% b2 C
printf("socket() failed: %d\n", WSAGetLastError());
$ }4 F+ u5 C" I
return 1;
8 m! X" N# N/ t6 F, _; d
}
0 d+ D B+ Y' X, U' O2 Q0 D T
server.sin_family = AF_INET;
8 \9 F' \% z; D# {, _. i9 z
server.sin_port = htons(iPort);
2 x6 M# K) d9 [7 G# t- a* s$ F
server.sin_addr.s_addr = inet_addr("127.0.0.1");
8 Q/ k x0 q# w: Z
3 g9 D5 k% K$ `. F
if (connect(sClient, (struct sockaddr *)&server,
% t! L4 q$ F/ \6 ^- \' @
sizeof(server)) == SOCKET_ERROR)
# H" [; @8 A- [, A3 M$ [
{
4 [- w6 D, i% @6 Z
printf("connect() failed: %d\n", WSAGetLastError());
8 ?' j) F E0 V* X
return 1;
8 L: o5 S4 h) o Q
}
' F" \4 L- m& Z
// Send and receive data
" ^# [$ i9 ]2 @9 @* B2 ?0 P
ret = send(sClient, szMessage, strlen(szMessage), 0);
3 T2 C7 t& t& t' G6 M- D6 A
if (ret == SOCKET_ERROR)
% y1 j4 J8 q& k* @; k; V8 a$ V
{
' G, J2 i5 j; A% L h
printf("send() failed: %d\n", WSAGetLastError());
3 B" R/ x1 S) P0 t% p
}
/ `2 z* n" Q, L' y$ Z, L
else{
/ t5 F! g+ M! q2 @$ B6 k1 f8 S @$ i
printf("Send '%s' \n", szMessage);
d4 p1 f- d' K5 q( Q% v
ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
0 L( |# h4 `% T0 m
if (ret == SOCKET_ERROR){
+ _- L- ]# L+ L0 |
printf("recv() failed: %d\n", WSAGetLastError());
6 D; \' }" j6 E- x) ]& D5 a8 ?
}
2 e3 e, P, A! Z5 h& Y8 O; E
else{
. z& ?+ F, s- d, O
szBuffer[ret] = '\0';
( d! ^& p' |+ w) t5 N0 v. L
printf("RECV: '%s'\n",szBuffer);
w1 ^2 H% I# |2 C: _
}
* y6 k0 ^6 f2 P: T' u2 p: z" Q
}
9 e W5 x' n/ b/ S
closesocket(sClient);
4 o" ^4 \3 T: o
8 `! w' i \7 I
WSACleanup();
3 F7 q a `+ ?' S
return 0;
" o/ A0 q# i) {7 l, Q/ x7 {' s
}
复制代码
服务器程序:server.cpp
/ G$ B7 \5 |% ^: u
#include <winsock2.h>
|! ?. Y% K0 h) j2 o, I* }0 x8 ]
#include <stdio.h>
% j1 _4 v; G7 X l( a/ \5 j+ y
#include <stdlib.h>
! P- H( j; [% {; ?7 b, U- G
+ T0 i* a" k; z8 _/ H8 m
#define DEFAULT_PORT 5150
" g( u1 ^! u+ e y& _ Z8 h
#define DEFAULT_BUFFER 4096
5 [6 w4 W" M3 L8 G0 y8 {
t- s/ B. A6 J1 |
int iPort = DEFAULT_PORT;
" q1 v# ~/ g& R S. M% N1 ^
char szAddress[128];
. ~; C2 x* M, y4 Y; E0 f5 j% A
' F/ N" ^/ }" S$ u4 C
DWORD WINAPI ClientThread(LPVOID lpParam)
7 ?) Y8 g1 y0 c7 H! C f
{
" q `- n* T: z: l
SOCKET sock=(SOCKET)lpParam;
1 d1 v7 O9 m( R- R1 }& h
char szBuff[DEFAULT_BUFFER];
4 ], G% v. c3 R, C/ Z, o' h8 K
int ret;
$ C5 e G7 T5 h( ?
6 Y' ]- W4 {9 q6 r
while(1)
! }7 l1 E. a/ D; R$ ]4 N
{
5 C& a6 t* g# d6 S: ~* n3 B+ G2 {0 }$ c1 E
ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
: x; s/ M0 B% M+ q3 [2 e
if (ret == 0)
$ L0 x! W, x5 c* b
break;
3 Y. ^- k; m* P
else if (ret == SOCKET_ERROR)
! X( F* q5 t. N" p/ P, b! e
{
l2 B. z: J& U, h. F" D: k& X6 M5 o
printf("recv() failed: %d\n", WSAGetLastError());
5 {. W, Q. }* W- }% U
break;
7 [" T2 `8 u9 V" E' R# P
}
9 r3 R7 \: x9 c
szBuff[ret] = '\0';
- H9 C6 @! x1 H9 `6 `/ k1 |
printf("RECV: '%s'\n", szBuff);
( @- M' J' o* t$ ?, U7 e4 i
if(strcmp(szBuff,"abc")==0){
3 [: s0 {: s$ c' J4 U) A) m
memcpy(szBuff,"Send the correct string!",25);
6 {, h! j, F* K1 E7 d/ x
}
. w4 h- ]& |7 X1 |% r& {7 S! }
else{
2 U, p6 C* ^& Q
memcpy(szBuff,"Send the wrong string!",23);
/ S: ~; M5 D" B0 x
}
4 S* _* k! t; Y1 }! w
ret = send(sock, szBuff, strlen(szBuff), 0);
# t6 \% d3 N8 ]9 V6 Q8 l3 X8 Q
if (ret == SOCKET_ERROR){
+ Q m3 m k: R( s/ \! t
printf("send() failed: %d\n", WSAGetLastError());
3 d+ \. m+ i# Y' i( e0 R, W$ G
}
8 C |9 T: h1 D0 y9 V: i
}
1 C4 X- l$ P$ X2 m+ b
return 0;
: N% f6 p1 g6 q# \" Z& r( R q5 c
}
5 e/ d: I& o8 ~* M
% t7 e9 y8 X) l5 ]6 o
int main()
8 Z6 L5 @4 P" J# R4 [( e
{
$ O% d% Y% i$ h
WSADATA wsd;
: E: ^) P" e6 R% ?1 M3 v5 ?9 u, k Z
SOCKET sListen,
6 N5 \6 ~8 A, E
sClient;
0 O- F) E o- L9 \# O# R
int iAddrSize;
- m# N$ I, v- b5 I* Z3 H; V
HANDLE hThread;
0 [/ j% H g- W3 X, w! k, I
DWORD dwThreadId;
& ~7 o* c, J& D# i
struct sockaddr_in local,
3 F; V" w) M9 e1 n0 J' b) i4 ?% S v
client;
6 D# L% b3 H0 U r% Z
- ^6 g; v# z3 q$ R- l) M: h
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
+ J9 l; X' _6 u* }. O7 ~9 o" U. X) C
{
% r) `6 @$ ?6 a
printf("Failed to load Winsock!\n");
0 J/ }, d. S- Q% j9 K( K
return 1;
' @& P) d9 r% L
}
4 y8 Y1 T9 d+ Z1 n, c- _: `
// Create our listening socket
4 g$ O+ Q6 E! W
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
; p& D8 f' F' j, m2 r" W6 j% g
if (sListen == SOCKET_ERROR)
( j! C2 ]) j" f; Z. u; Z* Y
{
7 f* l) U& j; V: M
printf("socket() failed: %d\n", WSAGetLastError());
$ U ?2 e- g, {& B& c) f# J) g
return 1;
/ B) a/ ~: `* y: N j" U w |
}
( X. Q) i& q/ [; A
local.sin_addr.s_addr = htonl(INADDR_ANY);
- u \; R3 t/ a" m( w3 O- S
local.sin_family = AF_INET;
1 f5 n$ W3 e* d' R8 X: t5 `
local.sin_port = htons(iPort);
2 o$ P; S" H2 L* i% s5 c
7 h# [/ D( y, O8 X' h+ R
if (bind(sListen, (struct sockaddr *)&local,
- e- [/ K1 ~; F1 }0 {1 e
sizeof(local)) == SOCKET_ERROR)
: v8 c# W# B9 N$ C; y9 ]
{
& ]" P: A; M$ f" ?. d* B2 }0 b9 g2 P0 R7 |
printf("bind() failed: %d\n", WSAGetLastError());
5 _" ]$ [ k( W( t$ E! s
return 1;
- i- a7 c2 O# N
}
% v& q5 K8 q7 N% s/ ]4 }' n; v
listen(sListen, 8);
3 @% Q; _3 Z3 y/ D% i# X* d
// In a continous loop, wait for incoming clients. Once one
/ Q( n8 a4 x9 d v0 w1 d9 |
// is detected, create a thread and pass the handle off to it.
+ O& F) T( T" q5 `8 t5 T
while (1)
% @# g! C$ N+ i N5 D* V3 C- ]
{
( G* V& V+ R. A
iAddrSize = sizeof(client);
: ]1 z$ ]: T' o: b3 i4 q
sClient = accept(sListen, (struct sockaddr *)&client,
' u8 B9 s0 a8 k1 |
&iAddrSize);
) W5 k1 C; f* \; @
if (sClient == INVALID_SOCKET)
% V" S; b$ @& r) m
{
4 s( @# ]7 X* ]+ j, r
printf("accept() failed: %d\n", WSAGetLastError());
" ~5 }4 o+ J g
break;
) f) q8 K1 }1 x
}
2 A1 F1 y. F1 Z- z, I' \6 }- l
printf("Accepted client: %s:%d\n",
7 L) {3 U$ X: ]6 A$ T @$ a; P
inet_ntoa(client.sin_addr), ntohs(client.sin_port));
: w0 a& y1 h2 z* E
& G* \) x, L+ b9 K: a
hThread = CreateThread(NULL, 0, ClientThread,
! b' h. |* o& i
(LPVOID)sClient, 0, &dwThreadId);
, U6 z- \6 O) A! p! U, p% [" V
if (hThread == NULL)
4 N- \' v$ k; S* b! ~
{
% y$ X( {7 u; A3 ^+ j/ `! s
printf("CreateThread() failed: %d\n", GetLastError());
% x3 n9 _2 q% O" [, c
break;
. a# x N/ Z# ]: C
}
- B5 Q! Y: k3 w% o; r
CloseHandle(hThread);
^5 K. c9 g& b& E- k
}
5 J! P* |8 H3 f% a9 S
closesocket(sListen);
; [; `6 p9 k% }7 \7 ^/ e# u$ `. m
# V' i# w% T1 }+ \* `* C* q: x
WSACleanup();
, @9 K- b) N3 ? p( }) v
return 0;
% i3 |4 K- d8 I+ t6 l- T
}
复制代码
$ Z1 D9 E, ` C# s! s- o
0 ^+ g: P1 x3 \4 {# r. C0 u! F1 C
5 M- S! s, D% k5 z& M* i
# B$ L$ o! u# N& i* J# O
4 Z- N; Q- F! Q# |4 `9 E# ?' E
作者:
admin
时间:
2020-5-9 02:16
作为服务器,你要绑定【bind】到本地的IP地址上进行监听【listen】,但是你的机器上可能有多块网卡,也就有多个IP地址,这时候你要选择绑定在哪个IP上面,如果指定为INADDR_ANY,那么系统将绑定默认的网卡【即IP地址】。
2 l% M6 l1 ?* W4 D
7 {5 ]* w9 r k6 g( i9 f4 A3 x9 o
作为客户端,你要连接【connect】到远端的服务器,也是要指定远端服务器的(ip, port)对。
# y9 ~% B0 w. V# |6 ]- h
当然,在这种情况下,不可能将IP地址指定为INADDR_ANY,系统会疯掉的。
* W. T# D- l1 m1 q1 Y- X
5 h0 R# b8 D% g; b: C. j# t
Server:
# j' z* Q9 p& ?8 M [
#include <winsock2.h>
: p/ M, g! e2 W6 M8 v5 x$ `" w8 x7 Q
#pragma comment(lib, "WS2_32.lib")
7 N0 ], I3 ^; a; R
& ~, z% X" w9 \$ I' G' |. ]% ]
#include <stdio.h>
5 A6 K+ u. j/ x) _( ^, L9 _
void main()
d. \6 I4 w8 ]2 U5 Z
{
2 d2 V6 c7 p. D& L, ]
WORD wVersionRequested;//版本号
% W7 v/ v+ m8 P6 y
WSADATA wsaData;
9 M* y3 u' P4 [$ j
int err;
+ z/ ^( [+ {* S; w
0 S' R, X' N1 w) X s3 X
wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
7 | R. v! h9 l5 O8 X* C4 X
//加载套接字库,如果失败返回
/ T) r8 z5 n: w g: T, `
err = WSAStartup(wVersionRequested, &wsaData);
# }- }* y$ `- v5 ^* s9 f% w8 |
if (err != 0)
% m% d1 n+ O9 n
{
/ H* Y" G3 |( A" r3 j" T- b
return;
2 O' {: N- o& k; a0 b7 ~. X
}
" v% L* }4 D m# c
K' t, I# m/ \7 K7 c2 m. i
//判断高低字节是不是2,如果不是2.2的版本则退出
0 a% K( l. P5 @9 F; b0 J- C+ C
if (LOBYTE(wsaData.wVersion) != 2 ||
2 I/ _! E: L$ e# f4 U( V
* B8 W" O" M+ i$ ~
HIBYTE(wsaData.wVersion) != 2)
* I0 B2 s# A; g5 ^" f) y
: g9 a; H; `# ^
{
, {: S$ O- ?3 ~* `# h
return;
; M* J. L$ K: L- ^
}
! t% w, n0 L R V3 d
1 \, d) C# o9 ~# A# L* w( X
//创建流式套接字,基于TCP(SOCK_STREAM)
& r# B) Y% J7 p1 s W7 d; G
1 |" T* M* U" t( K
SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);
! ]1 r3 p& ]2 @4 f! i( x6 c0 o. }
; i& M& p' k/ }2 a$ a
//Socket地址结构体的创建
# `/ P4 U/ H2 v5 Z3 w
: z$ _% S2 S& \2 N6 B! G1 v
SOCKADDR_IN addrSrv;
, K$ T7 v1 T2 y0 z! C6 S
4 a0 Q& \8 t. F7 j6 t
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
( U* V$ G7 x L) S6 ?
addrSrv.sin_family = AF_INET;//指定地址簇
' N" w. x- d* t
addrSrv.sin_port = htons(6000);
! O5 I) Z. D% W" C! p# z. q4 W) Q+ Z
//指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换
6 u. A# s8 i; v3 v |7 b2 I
2 B3 s' D1 o1 S8 x% h. @' s/ r
//将套接字绑定到一个端口号和本地地址上
4 o# W& d) C' d( {/ z( J
bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行
: t7 a& F6 O9 M. W2 G
& s! C0 _: ^' \! T8 C2 ?
listen(socSrv, 5);
1 L+ @, h! n& X1 w* V- H& m8 Q
3 W+ L6 F/ u6 |9 m
SOCKADDR_IN addrClient;//字义用来接收客户端Socket的结构体
; x" L( i0 B g& W- S0 H
6 _+ J/ u6 e& b& h, t+ ]) W
int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof
: l& c4 G$ b( j+ L c
4 o7 p2 L L( Z, e# E2 l* W$ l2 q9 }
//循环等待接受客户端发送请求
1 R7 {$ Y! f/ G5 }4 D* u
8 }+ Z( K a+ N, C1 o
while (1)
" [% F8 i. Y9 l% p* L# N
{
( \; L- D# J! E- \5 X5 [- @. [
//等待客户请求到来;当请求到来后,接受连接请求,
, w- I) x- T' M% u
& f2 z; Y0 u( D" O
//返回一个新的对应于此次连接的套接字(accept)。
( H+ J0 J+ x8 ^1 p
//此时程序在此发生阻塞
% ^$ y& Q0 A* W& M) F3 ~
5 r$ R6 f% t' c& x' n
SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len);
* \3 Z! n& l8 j: O b
" z5 h3 c/ Y% }' D- f; [
char sendBuf[100];
+ a$ S0 W! A$ g5 z4 A7 q
9 D* S- H' ]6 C$ Y" Y/ b
sprintf(sendBuf, "Welcome %s to JoyChou",
) ?9 y, f- a: d" N$ w
& h" s4 G4 U) n8 y" d
inet_ntoa(addrClient.sin_addr));//格式化输出
5 T$ L! ~" C E, p; ?4 Q
& |- C& {: q6 s. F1 [3 ?
//用返回的套接字和客户端进行通信
' j0 ]6 i- \: K+ @
( }8 i1 o) A( p( l- j
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多发送一个字节
8 \- Z9 E7 i! @/ w4 X
r" Y6 h# b4 b4 ^& t' p5 W
//接收数据
9 D4 @5 r8 }- P# j; \
! Q# L/ Y8 S6 ]- ^8 j. j. i
char recvBuf[100];
0 l6 T& e `, B0 h, \
( _/ v* t9 B6 l
recv(sockConn, recvBuf, 100, 0);
4 s# v+ D% M) V; e/ l# b6 y
6 a; V) Q8 |" E/ ^/ b
printf("%s\n", recvBuf);
5 `- A; ?" X' S$ s* H
closesocket(sockConn);
6 k- |7 R" ~: [+ |4 C
& N+ j0 |0 @2 P C/ X) ?
}
5 }: {% e& P+ U; H
}
1 S% b* X6 \& b6 o' n
- y% f) Z7 B5 Z) J* Q( G
. K' L2 }8 f5 \0 Q
Client:
% ~8 o1 v# |5 @& B" j) a
! I8 {6 J, k0 W2 h) b* k, I& `" y
#include <winsock2.H>
- b2 h) f# ]2 I
#pragma comment(lib, "Ws2_32.lib")
& Z, w( s6 \) `" P
#include <stdio.h>
- [. z% A7 o7 V8 {
#include <string.h>
$ W' {: a0 B& S8 B" r; k
6 _: h8 ^* P3 H* |" v
void main()
1 J. T: c* J+ G
{
* C" @9 J0 g B3 R* Z
WORD wVersionRequested;
. B5 x6 N9 A4 K- B7 ^9 ~
WSADATA wsaData;
' n0 u; S$ l$ L' l3 M4 @
int err;
& I4 n/ X+ `, z- I9 k. X
# ]: t. U" ]+ K) c1 P7 l
wVersionRequested = MAKEWORD( 2, 2 );
" r3 _7 Q0 ~9 {- Y1 g
9 o0 E" a1 v) B% Q. Q
err = WSAStartup( wVersionRequested, &wsaData );
7 `6 C7 d4 {8 l9 ]& t
if ( err != 0 ) {
+ Y/ }- C* _* n/ s* V" C0 b
6 Z7 g/ Q. o2 w- A: o0 b" P Z7 U U
return;
6 I! W; {0 M) V% w3 h; ]
}
; A" M, H* F1 F) M
" U7 M/ P/ z! e
, X. F# i, F. J* s8 x
if ( LOBYTE( wsaData.wVersion ) != 2 ||
4 o9 X3 q I: W4 h$ e0 l
HIBYTE( wsaData.wVersion ) != 2 )
: N1 S+ S, r7 {) `4 }# v
{
3 W, u- P& x1 j6 d3 o" ~) N; K
( \% c" f# { K- z
WSACleanup( );
, {( W# T, h( ~0 V; p
return;
9 Q- D5 H4 l6 i% B" x0 W) [
}
# x( p* H7 @$ }6 y9 @
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0);
+ L) V) L/ L; S# |7 X9 c
SOCKADDR_IN addrSrv;
& B% E$ \" }* D6 }
addrSrv.sin_family = AF_INET;
2 m2 l. ^' s3 y1 m9 `- k* M
addrSrv.sin_port = htons(6000);
. M. u( l9 y2 \, o9 {# `# w- Z
addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");//服务器端的IP地址
% ?6 `, t8 V U% W: s
* O ~ m/ i2 p0 ]* s4 O
connect(socketClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
* ` [9 `% L9 U3 ~
char recvBuf[256];
0 w7 i! q! ?; P" g$ `( \
char sendBuf[] = "This is Joychou";
$ }0 u) @0 n$ z/ q7 @+ V' H# B$ P8 I
recv(socketClient, recvBuf, 256, 0);
6 D- |' n4 R- p8 ^: B8 ^
printf("%s\n", recvBuf);
3 E: {$ G' s' S4 d! {
send(socketClient, sendBuf, strlen(sendBuf) + 1, 0);
4 F1 ?* K K& s+ o. V, c
closesocket(socketClient);
5 S; Y: M; }' m" o& d9 c; _/ E: T
WSACleanup();
+ A% K$ X" G* Y
5 u# e# M- d% b: @ `
}
复制代码
6 ]/ x" H7 ] Z, J5 p; e
0 k6 }' Z( s4 w7 j6 k% M: H: U3 @
欢迎光临 cncml手绘网 (http://bbs.cncml.com/)
Powered by Discuz! X3.2