cncml手绘网
标题:
一个简单的C语言的socket服务器和客户端程序
[打印本页]
作者:
admin
时间:
2020-5-9 02:14
标题:
一个简单的C语言的socket服务器和客户端程序
程序很简单,windows环境下的,客户端和服务器程序都在本机运行,在客户端输入发送给服务器的字符串,服务器收到字符串后会打印出来,同时与"abc"比较,与"abc"相同就会返给客户端,输入的是正确的,不同会告诉客户端输入时错误的。
7 D" I* e. a0 J
客户端程序:client.cpp
$ E$ C! A" s* D1 t- n8 d! q
#include <winsock2.h>
9 y$ H8 x# k! j& t# X
#include <stdio.h>
( Q3 M7 [$ A8 I1 q# f1 `
#include <stdlib.h>
$ w2 p2 w# `# V4 s! ^
4 m: d8 _( R" x0 s# b" Q
#define DEFAULT_PORT 5150
( {* g- \0 h9 j5 ?: W
#define DEFAULT_BUFFER 2048
5 H; [* ^3 N' s
5 E) I' C! H8 V7 K) v! }) i
char szServer[128],
% F: e6 E2 o; t) y. z
szMessage[1024];
( ^! ^% J* z' p( s5 U6 w
int iPort = DEFAULT_PORT;
0 k( v0 N% M. I: j( L) p# `2 D
' n6 o6 h, q0 ?( J
int main()
# \3 V8 {3 h* [" X& h
{
6 t. c% o) B! Q3 m0 \3 \9 @) f X: G
WSADATA wsd;
# k: B) ?) M" U- G, Q- p* `; u
SOCKET sClient;
8 b' Z k6 U: E, z1 k, L
char szBuffer[DEFAULT_BUFFER];
7 t1 j- m3 n) |6 ]5 n
int ret;
! @( ~) o4 x! t8 S/ L
struct sockaddr_in server;
+ B8 P( ~2 q2 ^6 u. |- n' l( v
struct hostent *host = NULL;
G h" g. c9 ], h# s! ^( A$ Q) R' E% X
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
W% P, }) d$ I7 x+ ~) K$ \6 F9 ?) E/ }
{
[% c0 U9 c) _2 Q6 S7 A, o W
printf("Failed to load Winsock library!\n");
9 s- h# B2 B( e7 T X
return 1;
, L: P O. f( _2 m. @
}
: j# i' f6 T [. u. u4 ^
printf("Enter a string to send to server:\n");
8 z# |0 e8 P+ N" w
gets(szMessage);
. _4 H8 |0 c- ^2 }0 G& a
// Create the socket, and attempt to connect to the server
; r4 x# e/ C5 J3 R; H% S
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/ f/ H4 V& I2 N4 w5 T, V( N
if (sClient == INVALID_SOCKET)
! Y2 s4 D/ X; ]" k, I5 i
{
9 Q+ [6 N# L, P$ w- d
printf("socket() failed: %d\n", WSAGetLastError());
5 m$ j# t# J1 k/ r; ^
return 1;
3 p) q1 {2 Z3 R( @! m9 \
}
0 U/ [& X2 P% o
server.sin_family = AF_INET;
4 K I) e0 k$ L; k+ c9 @- a
server.sin_port = htons(iPort);
3 ]" K* h% m$ w: N3 m$ J0 V
server.sin_addr.s_addr = inet_addr("127.0.0.1");
: }+ U) g5 B, ]. i
3 S; i" O! B. L( d
if (connect(sClient, (struct sockaddr *)&server,
# S- M, _9 |1 d+ ]7 M; F& C, V. h
sizeof(server)) == SOCKET_ERROR)
# g! L1 b* [: H+ A* z/ O
{
5 {, H9 k* S- p. Q, P5 [( d/ I2 \; k$ _
printf("connect() failed: %d\n", WSAGetLastError());
( ~2 O9 d) C- y) X; L0 J& X
return 1;
4 E/ ^# _) k7 m0 d
}
# P9 _" C w. y& S; n
// Send and receive data
/ D8 `5 |# s) {6 h
ret = send(sClient, szMessage, strlen(szMessage), 0);
9 G6 d' J+ W1 Q" h* F/ K
if (ret == SOCKET_ERROR)
) S6 l; s- X7 f& m8 g8 N
{
8 Q* H* k; {& V9 y
printf("send() failed: %d\n", WSAGetLastError());
" E! U/ M" n* C8 K6 a% S: E
}
+ v! E* x& X2 P. t
else{
" H% U2 E( `' U; E
printf("Send '%s' \n", szMessage);
9 d X7 F- m9 }9 j" A- h1 P' P
ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
* j" q1 V8 M2 Z4 c3 A+ T& @( \# t# T- O
if (ret == SOCKET_ERROR){
8 `+ Q4 N* ^% o( _: d1 U
printf("recv() failed: %d\n", WSAGetLastError());
0 s1 U+ k [( I! \. `
}
7 u: \* m8 f# z4 w% a
else{
2 }! B2 t3 J& _, E/ s+ ]3 q, `
szBuffer[ret] = '\0';
* j, N- B2 u8 Y: |& k! j) @
printf("RECV: '%s'\n",szBuffer);
* }0 E/ B: b5 |4 @, \
}
+ d/ e+ o5 ^& @/ v/ h. K4 s5 G
}
0 L- [9 I. v+ u- o8 D* F
closesocket(sClient);
9 b( l, B) R7 E8 Y
8 `2 U7 z1 I$ `* a
WSACleanup();
/ l' Z0 q9 h3 p* j, s
return 0;
; K2 [% S0 y3 ~" c2 |' O
}
复制代码
服务器程序:server.cpp
2 [& y7 E4 V( g7 a3 ]1 A6 Y
#include <winsock2.h>
) Q. N2 z. V0 }1 B" E4 ?
#include <stdio.h>
% S. d# K3 c. {! j7 i8 [1 B
#include <stdlib.h>
- D; ]8 a4 U* w$ `+ I
" k. i3 E/ X: x5 s8 I' I
#define DEFAULT_PORT 5150
! Q* B( s4 Z$ o) W6 Q0 k9 V1 F7 A
#define DEFAULT_BUFFER 4096
' c0 Y0 h9 U0 m7 `( K8 q; \
8 h6 _! e$ C. a5 C
int iPort = DEFAULT_PORT;
M- k. N2 l/ z: L
char szAddress[128];
6 y$ D# n o1 @) L3 ?& m
- o5 b. O) q9 I
DWORD WINAPI ClientThread(LPVOID lpParam)
$ O. [' i0 K% S4 E" ~- P
{
( R6 O* c. k- {5 s/ k
SOCKET sock=(SOCKET)lpParam;
4 @) y3 N7 {* N" j
char szBuff[DEFAULT_BUFFER];
3 j9 m( d& c7 z' v
int ret;
. N S* q t1 I) g s
9 t4 h1 P- x3 Q ?" t: m5 t; P
while(1)
7 X5 q6 ~! m4 @
{
& e O0 V$ V9 Z! z& R: r
ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
# R1 [8 t- [; o. c9 a
if (ret == 0)
* Z* i( U1 A3 A# h
break;
4 ?" q# o4 I! V
else if (ret == SOCKET_ERROR)
2 k$ M) f# H5 |- [, \# {
{
; m, I9 Z6 B& P7 [) r9 ^
printf("recv() failed: %d\n", WSAGetLastError());
. I/ f( l' ]: l0 U
break;
0 }* \0 M W1 R0 G) H
}
1 |9 T( w4 ], y+ ]. u; x/ S
szBuff[ret] = '\0';
3 \9 x# U$ D7 N4 z2 J1 v8 a
printf("RECV: '%s'\n", szBuff);
7 ]9 V Y: z U ]# Z9 o) r
if(strcmp(szBuff,"abc")==0){
+ Q' a, q; U# ]. [
memcpy(szBuff,"Send the correct string!",25);
( F( g9 F1 c0 ]2 _
}
% @, h7 |8 O) J
else{
! a" v% p1 i7 Z( q8 s$ e
memcpy(szBuff,"Send the wrong string!",23);
( B0 i, t; r$ y6 C/ i6 [' J( \+ k6 R
}
5 g7 n9 o5 t' R0 ?2 \4 e7 U. h" g
ret = send(sock, szBuff, strlen(szBuff), 0);
0 V1 ~8 \# w0 c3 T$ O( X( E
if (ret == SOCKET_ERROR){
% c, S) \: I/ l8 D
printf("send() failed: %d\n", WSAGetLastError());
: O% M' O5 @, [; D, ?' b2 \ P
}
0 I m ?; J* @& T5 h% t/ F, E9 a
}
6 Z2 N3 T: S5 R- }* u* g
return 0;
, a; ?2 m# Y6 B5 ]* l- Y6 S
}
X! C h8 q" A3 D2 G
* z' t2 y* B& Y+ E" q1 e. R
int main()
# i# ?! x. S& z! k2 s) Y N; v0 b1 ~
{
Y# u, M1 [3 x7 o
WSADATA wsd;
f& m4 [2 m1 _4 O2 w4 `
SOCKET sListen,
! m3 f9 g, q+ F m/ K: J# [% ^
sClient;
+ M% l4 H$ L* l6 ^% M+ d6 z
int iAddrSize;
5 j' C* Z0 I) }& w p' h
HANDLE hThread;
6 k; i) t! P, x2 P M
DWORD dwThreadId;
8 G$ i' s# m$ z H8 P1 S2 A
struct sockaddr_in local,
2 l. G& P% E6 _
client;
: C( K0 Q# w( I* l
- U2 w6 f: l: R
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
L& Y: r \2 c. {# S7 t
{
4 _6 P8 b( [- u G- }
printf("Failed to load Winsock!\n");
# p, X& w# \3 B7 H2 f" {7 I
return 1;
; ?0 s* {: A" [! `, _: b$ I
}
V0 _) L: [5 Y+ N4 j
// Create our listening socket
# @! r3 a- ]$ |1 m" H" j- v
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
$ S; V. J2 Y6 h+ F. o/ l: w; c
if (sListen == SOCKET_ERROR)
1 J* j) R* n3 O' R$ ^' U/ J
{
( S; u8 k! z# n2 k c
printf("socket() failed: %d\n", WSAGetLastError());
+ X8 c X" K' H9 D7 G2 d
return 1;
) r: |/ a9 \. G) w {- O7 M) u. {
}
5 ~! n7 [+ T C8 Y: W# q
local.sin_addr.s_addr = htonl(INADDR_ANY);
% x# D# p% W" E
local.sin_family = AF_INET;
) m1 b/ b( {# p
local.sin_port = htons(iPort);
% X( X- J) M9 q% S3 L$ c
2 s" n& A, U( q' @' l
if (bind(sListen, (struct sockaddr *)&local,
! s% H5 x+ ]5 \9 s v
sizeof(local)) == SOCKET_ERROR)
R- p( S2 R7 ^- H0 A
{
# x$ i& m/ y, Y
printf("bind() failed: %d\n", WSAGetLastError());
% C' X* g( l6 D5 N/ o, v1 _
return 1;
! _# K8 d- D1 P$ W6 e) W
}
( k) f4 c3 {1 ^( k: j
listen(sListen, 8);
6 N! R! U' k; V" B6 E$ h
// In a continous loop, wait for incoming clients. Once one
7 T, j+ l: j# i- m
// is detected, create a thread and pass the handle off to it.
2 C+ x8 `9 t1 M$ n3 }* Q; ~0 K
while (1)
' [+ l) ^: D$ j/ y
{
2 D3 [* @ Y+ x) I. G; q; K
iAddrSize = sizeof(client);
7 L0 b; x9 M9 E) S, Y
sClient = accept(sListen, (struct sockaddr *)&client,
; Q! x' W- o8 t! V5 l* m3 L
&iAddrSize);
# F$ J: h6 M" M( D
if (sClient == INVALID_SOCKET)
& m/ v @* R( v# g1 w1 p. ?
{
5 J9 c( @6 k. t
printf("accept() failed: %d\n", WSAGetLastError());
+ m4 @8 j' C' m0 d2 P) E! L! s
break;
" W; K' n3 `. p9 g' R) A) H- e
}
o6 }2 e8 C( Q# S. U w( x- ]
printf("Accepted client: %s:%d\n",
* T3 {1 J, I. F
inet_ntoa(client.sin_addr), ntohs(client.sin_port));
2 U4 s5 X9 n V7 ~
$ M" q2 \, s9 t: c- q; h
hThread = CreateThread(NULL, 0, ClientThread,
q" ?0 f- r8 R) |; g4 }( C8 M9 P
(LPVOID)sClient, 0, &dwThreadId);
9 M9 J b5 P8 l q5 K1 X9 F
if (hThread == NULL)
2 J7 H' r! p4 V2 |1 b
{
6 Z- G9 \7 }" I" v
printf("CreateThread() failed: %d\n", GetLastError());
$ {& o% k# z- G9 }$ T# q3 ?
break;
! q4 z" P, d% M8 ] `
}
* \" m+ k, J) D: R( o) G9 {8 l% e8 x
CloseHandle(hThread);
8 ?; B- K0 [, b5 C
}
, f* K" b) B( i8 n+ r, ?; h
closesocket(sListen);
9 j- j I {: ]/ o; F
L0 b: U8 k3 A
WSACleanup();
" K7 t" Q0 I& o
return 0;
- i w) _- I. X! O9 T
}
复制代码
* m% G+ T5 L: ^$ B! T; }
. v" H# p7 j3 z5 D
: p7 o; m, D5 F0 e, ]) o+ q
" W3 N. |: X# ]4 I( j
2 d6 m' D: p. T/ m: }
作者:
admin
时间:
2020-5-9 02:16
作为服务器,你要绑定【bind】到本地的IP地址上进行监听【listen】,但是你的机器上可能有多块网卡,也就有多个IP地址,这时候你要选择绑定在哪个IP上面,如果指定为INADDR_ANY,那么系统将绑定默认的网卡【即IP地址】。
0 f, K) \1 U8 A3 ^
, s* N3 G1 A9 n
作为客户端,你要连接【connect】到远端的服务器,也是要指定远端服务器的(ip, port)对。
! `7 P6 F! a4 X9 U+ e9 s$ v
当然,在这种情况下,不可能将IP地址指定为INADDR_ANY,系统会疯掉的。
# D3 V. h; N5 k5 D/ e( E
) ^. h$ ~6 T7 e$ ]9 D
Server:
_' g7 r+ H1 r3 k
#include <winsock2.h>
3 u Z$ r( Q* V% @) Y; c, X9 x
#pragma comment(lib, "WS2_32.lib")
3 {: n2 e1 e- L* {% X2 g
- @& s2 i h9 G
#include <stdio.h>
4 i! Q; y4 W- B9 ]7 G
void main()
, T# `3 e3 ~9 B) W K9 N* a
{
+ k$ l ^8 f2 \+ g X: q3 o
WORD wVersionRequested;//版本号
- o0 P$ Y1 k* }2 j* b$ Z, O
WSADATA wsaData;
: ^( P4 `7 E% b( L" P6 M( d. K* N0 ^
int err;
7 y+ W1 e+ h9 z
* r" K! \+ [6 J
wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
! T: b8 _3 Q) X" `+ F! ?
//加载套接字库,如果失败返回
4 i6 T' E, }/ k3 s# L% A, P: J' L5 f
err = WSAStartup(wVersionRequested, &wsaData);
" c& t( y3 ^: P, \
if (err != 0)
x4 Z4 Q' C6 O$ e/ Q7 Z5 ~" m* ^" Q# R
{
; S C' x2 B" U; E3 {
return;
: w- z/ W. n* C9 Z5 f- b" o
}
. R7 S+ b, M) m; |; {
& `3 s& i( S8 s1 I1 Y# V2 |6 V
//判断高低字节是不是2,如果不是2.2的版本则退出
; H V' f' E% d! \8 h$ V6 G
if (LOBYTE(wsaData.wVersion) != 2 ||
/ N5 b" r: A# p! G! q
4 D9 D- B7 Y8 S! g4 y
HIBYTE(wsaData.wVersion) != 2)
& O8 U) \4 L5 i) a' Q8 y3 Y
/ N5 }/ t. I' \
{
. M( M, O. g3 T3 ?
return;
9 u2 e v0 M8 |% K( ]
}
0 {9 W3 F& k- H, @
. Z: V. ~! ]/ L4 a5 e
//创建流式套接字,基于TCP(SOCK_STREAM)
! t9 n; }7 Y. C: j* \: B: h
+ a3 t2 Q% S W7 ]. m& m" q
SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);
& h3 a1 }8 P; X# t% A; c" o+ j
' \% L, \" B E9 m' u/ }+ p
//Socket地址结构体的创建
4 j3 v1 C9 I8 h4 q0 b
- Y6 @' h% o8 b& W
SOCKADDR_IN addrSrv;
; a3 k$ O7 x* ?5 K& n! n# G
* S# p0 v/ v( b9 \
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
; x8 j2 b9 U/ k; _; R! ~& x
addrSrv.sin_family = AF_INET;//指定地址簇
+ e6 o2 R1 d8 W/ l' x7 {
addrSrv.sin_port = htons(6000);
: f* q l3 Y. O4 N
//指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换
) | K3 h+ A/ w8 c4 g: M ?
2 q7 g; e ]4 _1 w1 l" z: |& Q7 c
//将套接字绑定到一个端口号和本地地址上
e" [1 R8 u1 A x' M! t
bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行
) K' n3 s+ n& \2 E5 F2 O7 D
! m2 e% Q! c) W& w) ~
listen(socSrv, 5);
; b" ?2 J: b" l/ y8 B" I5 q
2 e3 M3 l3 P, P9 y% e
SOCKADDR_IN addrClient;//字义用来接收客户端Socket的结构体
0 m6 L; v8 [, {1 l, y( ]
8 p. ~ ?. c0 b, B }! E
int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof
+ N+ y, d. u% S. n
/ v+ |1 y& U" g
//循环等待接受客户端发送请求
# @/ T& J, {: `; l5 n
4 ?* J* j0 |# I$ o! x& ^* ?
while (1)
) L3 M7 Q& I2 a: A
{
8 ]. }: `9 W* K; u! Z1 {& x) x" V
//等待客户请求到来;当请求到来后,接受连接请求,
# n& S1 K0 t3 h2 ?; u
' a4 W3 {4 x/ h: p% B1 d
//返回一个新的对应于此次连接的套接字(accept)。
+ ?! k+ [: ]# M7 H) K. A4 x) ]) U
//此时程序在此发生阻塞
1 C; x3 |, \& N% j
' V6 D) p5 D) r" a; T
SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len);
! s! m5 z# E* L# ?
* S: k: I4 h/ o, h6 x
char sendBuf[100];
7 T& s- r6 _( f. k' u; q8 Z3 x
L% Q# B$ p# c1 E
sprintf(sendBuf, "Welcome %s to JoyChou",
* x/ r+ l8 d: G, E- X
1 U1 s, ?8 {' A3 n$ V0 {
inet_ntoa(addrClient.sin_addr));//格式化输出
( ~# r. N% @& r3 M9 P
, }0 j4 X. P$ z& ], G# t5 t
//用返回的套接字和客户端进行通信
" Z1 a+ F' ]& a9 K5 U" W
& c7 p! v d& {/ I1 c" f
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多发送一个字节
9 N% i* E7 u9 h7 W- A$ v% ^
y) i5 F2 l2 X3 |% i5 ^2 O
//接收数据
, @' r9 z+ J D4 X3 N; W
3 k% o) E% F. {* |) m
char recvBuf[100];
0 }% Z! R M& p3 y+ X3 G" M
) U m* a" ~# P( C
recv(sockConn, recvBuf, 100, 0);
! y( s" U' B7 r9 ?6 {+ v" w, r
1 {3 M$ O6 p- |; T, Q0 g
printf("%s\n", recvBuf);
9 Z) \1 o" b2 h
closesocket(sockConn);
. s% u# s; K7 z% _
4 L1 g" T' v# X4 d
}
0 d2 g) U4 c9 p" E" M- c6 L) B
}
3 }$ a- U# v+ U5 R5 b
* O1 @ X! @ p: O0 }+ ]
9 _0 l g3 s) s1 m
Client:
0 S: H8 Q# f0 T8 ~) Y
4 ]; e( ~/ H7 V- m8 K% o
#include <winsock2.H>
% Z4 h) y4 m8 S
#pragma comment(lib, "Ws2_32.lib")
/ ~& y( Z/ [) w+ z# r0 b: v
#include <stdio.h>
- _- c; c8 I2 W) H
#include <string.h>
. s' x3 I0 a6 m9 c
b) ] K6 O0 G
void main()
9 f" r% G8 r! x& t: u
{
* y/ x7 f, n# b9 i
WORD wVersionRequested;
$ A, n/ w0 g+ j0 o _3 J6 O# H
WSADATA wsaData;
0 i/ I% s1 a/ s2 N' s9 G9 Q% B( J% B1 [
int err;
& i, Y. `8 ^* S g- I `/ ]
7 W, n" M/ Q; i$ s
wVersionRequested = MAKEWORD( 2, 2 );
. c/ L8 u) t' U# ]
: T; c+ `9 ^/ o: i& ^
err = WSAStartup( wVersionRequested, &wsaData );
. B, Z9 }5 Y& f- J* u7 U" q9 K
if ( err != 0 ) {
' N3 j. ` y( w# p0 j- I: Q
8 ^7 s) }2 k/ a9 a$ {
return;
- | I& S9 v8 _. z) M! G
}
1 e8 v T) a% Y9 t0 E* ]8 a c+ U
9 W) C" \) r9 O4 u; B* k
5 h4 Z- W( F9 D5 X$ L/ B
if ( LOBYTE( wsaData.wVersion ) != 2 ||
|3 ~- K8 x+ i4 z B
HIBYTE( wsaData.wVersion ) != 2 )
/ p- D6 Q6 h, h I
{
2 X4 m# ~* Z; P$ ^6 |
1 i8 R. K/ K1 L
WSACleanup( );
! }8 \; Z) }% b4 K/ j# i5 J* H
return;
: k r3 ~+ q# A. H
}
# y+ H& g' c1 D1 t+ t$ d
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0);
4 G* ? |/ S* }# J* \! K
SOCKADDR_IN addrSrv;
/ u4 r- Y: ^6 l
addrSrv.sin_family = AF_INET;
' A; U' a0 }; `0 e2 P5 M! W
addrSrv.sin_port = htons(6000);
5 C# ~& M# D1 q, x1 `" w
addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");//服务器端的IP地址
* n3 u, A3 K I0 c. e
8 U J* b2 H3 N/ K. ~* n
connect(socketClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
- q9 p/ z3 H3 {5 C& z
char recvBuf[256];
& R. q. w6 ^, V) N7 I+ f) W/ A9 `
char sendBuf[] = "This is Joychou";
+ x& y# \+ _/ K
recv(socketClient, recvBuf, 256, 0);
% Y8 _5 D- A/ v
printf("%s\n", recvBuf);
* ~; R+ E+ M/ [
send(socketClient, sendBuf, strlen(sendBuf) + 1, 0);
% ?- q6 m- p& M/ ]4 h7 z# m" w
closesocket(socketClient);
$ T" X9 G4 [7 X
WSACleanup();
! v+ z7 I) q9 H* F/ E1 T: h
+ k2 P3 f F: v- Y8 z/ i
}
复制代码
# Z' Q$ Y9 r3 t/ Q E
, k) J6 k! G$ x6 I. h- P
欢迎光临 cncml手绘网 (http://www.cncml.com/)
Powered by Discuz! X3.2