cncml手绘网
标题:
一个简单的C语言的socket服务器和客户端程序
[打印本页]
作者:
admin
时间:
2020-5-9 02:14
标题:
一个简单的C语言的socket服务器和客户端程序
程序很简单,windows环境下的,客户端和服务器程序都在本机运行,在客户端输入发送给服务器的字符串,服务器收到字符串后会打印出来,同时与"abc"比较,与"abc"相同就会返给客户端,输入的是正确的,不同会告诉客户端输入时错误的。
5 s0 Z) }* ?! B
客户端程序:client.cpp
! r2 |) r% d% g5 Q- v; V$ H. ^ X- F
#include <winsock2.h>
( l& x: p! i( U( c; {
#include <stdio.h>
/ F7 T: W+ ]. c
#include <stdlib.h>
9 L% H5 @" O9 }# ?& \
" I# E$ p4 O/ c1 S8 h/ h
#define DEFAULT_PORT 5150
1 X- U$ V7 Q5 O+ V/ R
#define DEFAULT_BUFFER 2048
! z6 \: B: s8 D% h
! a* U5 p7 b! w# G1 V; ?% `
char szServer[128],
( h X3 i% u3 P; t) X
szMessage[1024];
$ W* Q, u [% U6 V
int iPort = DEFAULT_PORT;
; _6 g/ j. m* T' i/ j
. Y% \* e [! |& u7 ^6 V- |
int main()
; \% _) `% j3 Z" r1 c' L" S; ~( }
{
( L1 L$ i, h b! k" N$ g# M Y
WSADATA wsd;
+ N8 {$ H9 ?+ J0 S' D: C/ x" b/ B
SOCKET sClient;
+ ^ T; L5 v5 u# w# q
char szBuffer[DEFAULT_BUFFER];
. p! E, J* J/ _ e' p
int ret;
6 k. R* U$ Z3 }/ R5 h
struct sockaddr_in server;
( u$ u+ G0 m) z& z
struct hostent *host = NULL;
/ s0 g8 a; q5 N' I" h* W/ T' K
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
, R8 L$ M0 X4 h2 ^* Y6 d' C
{
% l, {, S, k; a: Y3 T
printf("Failed to load Winsock library!\n");
; b4 L& |% `* D7 Y
return 1;
; b$ v0 R- L+ ~! X1 O9 I1 Q) V
}
$ f' C( F2 ?' r) Y
printf("Enter a string to send to server:\n");
8 y r% ^0 j& c2 Z$ i
gets(szMessage);
: u3 x. w0 U& \7 T4 d, w8 u! g
// Create the socket, and attempt to connect to the server
: P# B# O* p% F \6 _ i3 w
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ d8 C& O' {$ n3 |6 w7 |
if (sClient == INVALID_SOCKET)
9 u7 e0 \2 E% _4 g6 j/ I
{
6 ]8 [3 i, |( O! Y
printf("socket() failed: %d\n", WSAGetLastError());
4 P" r6 K6 A* e7 X3 i
return 1;
; {) p, |. q" `: m0 I( u- X
}
/ E; }/ P& j" w8 [+ a. B
server.sin_family = AF_INET;
. m B4 ^/ d- C4 m" x/ U
server.sin_port = htons(iPort);
" N" I8 x# w8 e# d- m+ v7 _. p; [
server.sin_addr.s_addr = inet_addr("127.0.0.1");
% d) D& T% D; G, i) ~7 P
' t# L$ }2 ~# r2 N0 N8 S
if (connect(sClient, (struct sockaddr *)&server,
3 u: }% y( ]# h+ @" h2 o/ d9 X$ u
sizeof(server)) == SOCKET_ERROR)
7 j1 `; x5 @4 n1 P' t3 p
{
4 n9 z( ]. D; a& {$ t6 l
printf("connect() failed: %d\n", WSAGetLastError());
2 A3 ^1 V- S' C# m
return 1;
N, W9 k* H1 ^
}
$ @; u# l3 o& K* a- R/ l' m; u8 m
// Send and receive data
. w- [. b# M7 ]+ b" @% W
ret = send(sClient, szMessage, strlen(szMessage), 0);
9 N' Z t$ K/ x# Z2 t& }6 }8 u7 Z
if (ret == SOCKET_ERROR)
' k8 g9 e0 k7 K2 r% ^' N+ u
{
3 [2 z. P) }* V
printf("send() failed: %d\n", WSAGetLastError());
6 V& q F5 d, ^3 F: Q! n7 ^
}
+ ]' S: L& C! @' l( a
else{
' [: f1 }! m ~& G* S
printf("Send '%s' \n", szMessage);
1 J: _" [7 |/ e4 T9 `
ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
/ \, _; F# n* z5 p
if (ret == SOCKET_ERROR){
3 B, R7 L& ` O; w3 h+ _8 G k
printf("recv() failed: %d\n", WSAGetLastError());
0 ]9 H: R2 b9 |1 o
}
- x+ C( D5 T* O) Z
else{
~7 n0 P4 ^" h6 o! a) ~2 R
szBuffer[ret] = '\0';
) h3 t# l0 t/ S
printf("RECV: '%s'\n",szBuffer);
/ G/ H' A& Y. L0 e
}
' E* A2 v8 M; R8 z5 o3 F2 N: a
}
" Q% A* c8 W5 |# M( @8 i* I
closesocket(sClient);
; D' s, W& e0 l7 [5 O
/ n, Z9 L0 f; }/ E* }" J, a! p
WSACleanup();
" ~5 s5 a2 h/ a) n5 P, S
return 0;
, e0 m8 Q3 T- l' Z7 @8 u
}
复制代码
服务器程序:server.cpp
/ i) j- u% U; `- k5 O1 P. @
#include <winsock2.h>
% K K- ^' g) R' g4 S- b V
#include <stdio.h>
6 j$ M L8 u$ J: T
#include <stdlib.h>
& L3 E) \7 W4 V; ~
# [! M8 O9 ^2 }3 k( X/ [9 w
#define DEFAULT_PORT 5150
0 X8 b, Y' D ^/ b8 E
#define DEFAULT_BUFFER 4096
2 ~: F8 h1 ?. z
' Z k w W6 F+ \/ r% T
int iPort = DEFAULT_PORT;
, v- M9 ?! X Z2 M( A; o( T3 h
char szAddress[128];
j d. G2 I$ ^! I$ m
, Z' p$ K' S+ W3 c9 d; [, e8 G
DWORD WINAPI ClientThread(LPVOID lpParam)
& S2 u" }' g5 F A- l
{
) t9 {! Y4 H$ u! J S2 m0 `3 o7 a3 T
SOCKET sock=(SOCKET)lpParam;
+ ?: F5 i9 Q: f3 p7 |
char szBuff[DEFAULT_BUFFER];
$ B1 A/ j( P* `
int ret;
7 j u! X! t0 c1 m2 ^
! A( N! M- `$ t6 e% L# w: A3 S
while(1)
& L5 q3 V& B; {6 t$ _
{
) O# o/ b7 e. I8 Q
ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
! W. E) c/ C2 f6 `
if (ret == 0)
4 }7 U) @- B+ x
break;
6 A m' F, R3 F( X- X
else if (ret == SOCKET_ERROR)
6 {! `9 J( d" ], N# Y, {! P$ `
{
: }9 L% b+ i o7 a" b/ T+ ?
printf("recv() failed: %d\n", WSAGetLastError());
/ @. }! F+ b/ ?
break;
5 q$ e( b `+ p* R* q
}
s) }9 A( D$ R E: {
szBuff[ret] = '\0';
# |4 c; R. c9 X9 |" x# A" n! e1 B4 u4 {
printf("RECV: '%s'\n", szBuff);
9 E4 [0 Q) I, Y; P; \3 U
if(strcmp(szBuff,"abc")==0){
6 e' C7 J! n/ ]; h
memcpy(szBuff,"Send the correct string!",25);
\$ f9 E9 U# C) W
}
: `. }+ I! w3 }0 y) v; W1 j" w
else{
) z+ m5 u8 G) F) O
memcpy(szBuff,"Send the wrong string!",23);
, v4 l, i' y D7 I" O
}
% b+ Z, X: f1 O, j- x
ret = send(sock, szBuff, strlen(szBuff), 0);
& U4 o: `' z+ C) V
if (ret == SOCKET_ERROR){
! F0 r+ B g: c3 Q
printf("send() failed: %d\n", WSAGetLastError());
: [/ U O! E6 Y* b8 k$ n
}
% U1 Z3 q8 G1 w3 H0 O% g
}
9 @8 i3 [& O0 X. X* Q7 Q
return 0;
5 Q$ t( y& B) t* Q
}
4 C/ [* O# Z E& L! ]7 V
* e( o6 Y w9 n7 ?$ }
int main()
) w3 U& \. z5 j
{
0 ?6 r; ^4 X6 ?( w8 Y1 B: z8 M
WSADATA wsd;
3 j1 o% N- z% q0 u* Z' j _; T
SOCKET sListen,
& M {! a) a3 t u. N
sClient;
, U! C! {0 e& X" c
int iAddrSize;
" F+ x2 ]1 W: V l+ d8 y
HANDLE hThread;
- ~6 x+ x( B! W; ~( i
DWORD dwThreadId;
( n5 o a. N- d0 m# r
struct sockaddr_in local,
5 X& \9 ^: L7 n% a
client;
; [9 G7 f0 @( E$ g& j
+ U0 a3 Y+ n% c4 r
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
9 G5 i5 b+ i' K( A1 S9 u2 f0 a# j
{
0 I8 o5 l0 }9 p2 O* r
printf("Failed to load Winsock!\n");
: ^, r u+ x8 }+ a# I+ i0 g& y4 L3 L
return 1;
: A; m7 q% m# j5 R8 G I
}
: o: h7 A7 d* R# [0 P6 N
// Create our listening socket
' Q P# [2 z: u: g/ D
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
) H9 f% ?$ A* V& D3 D3 G
if (sListen == SOCKET_ERROR)
* `( T* U8 d9 v! C' j1 a5 i; J
{
1 e& O/ e4 W0 Q) m% h8 R- @9 d
printf("socket() failed: %d\n", WSAGetLastError());
. g. g4 k7 }) a1 }3 ?7 P
return 1;
& A+ N6 R. R m5 ~
}
- I! g9 a1 Q4 e5 P2 v1 r8 J4 Z$ N
local.sin_addr.s_addr = htonl(INADDR_ANY);
+ T) @8 c3 O4 Q0 I2 U+ ~0 ^
local.sin_family = AF_INET;
6 l5 l$ x p' C
local.sin_port = htons(iPort);
: P. w5 e- E- z% Q! S! d, e* b
2 T' t4 S3 [& b) n$ F2 E
if (bind(sListen, (struct sockaddr *)&local,
% ~- W+ {: M" N' y, D# u `5 h r
sizeof(local)) == SOCKET_ERROR)
* |; Z1 ^: V1 E7 v7 }$ H
{
% j* d, B/ Q% N9 X
printf("bind() failed: %d\n", WSAGetLastError());
9 U7 N. W; m8 [2 t' G1 E1 ~( L
return 1;
9 c9 B Q9 C" h
}
6 u& D5 ?1 _* V4 l6 D
listen(sListen, 8);
" B8 z+ s4 q- ?4 S
// In a continous loop, wait for incoming clients. Once one
# }4 V) |$ `8 ]2 V2 O
// is detected, create a thread and pass the handle off to it.
0 r" i1 M3 S1 W; R# {/ f
while (1)
+ P4 Q1 P7 k9 h" i
{
! `& O0 N$ x/ j2 t$ i7 r: S8 C: e
iAddrSize = sizeof(client);
3 v+ v5 F a* h, B1 A) g
sClient = accept(sListen, (struct sockaddr *)&client,
% H/ k$ Q: W* _1 _
&iAddrSize);
/ E0 j# t$ b1 }1 M4 S p% b
if (sClient == INVALID_SOCKET)
" q: v$ }* u3 N: w1 z) J
{
6 N+ W# M) F! I9 C% v2 f" G
printf("accept() failed: %d\n", WSAGetLastError());
: Z0 g8 D+ G& i& H2 h/ w: ]
break;
- r3 i7 ^5 y/ g2 |7 |2 V2 r
}
1 j$ x3 l, B: B2 v
printf("Accepted client: %s:%d\n",
/ d0 N! `: `/ C9 }6 U6 \) A
inet_ntoa(client.sin_addr), ntohs(client.sin_port));
, \6 i! U. E: G. a2 g
8 c8 w; L6 i. }1 O
hThread = CreateThread(NULL, 0, ClientThread,
: ?0 n( l) l. N, r) D4 _4 o
(LPVOID)sClient, 0, &dwThreadId);
! i3 ~+ c1 O0 D$ t
if (hThread == NULL)
3 ]- [! `1 k Q1 p9 J" T
{
3 m, Q: Z k: y3 e6 ~, A2 R: o |9 O
printf("CreateThread() failed: %d\n", GetLastError());
+ e# A# @9 Z5 ^5 N( L: [9 Y
break;
5 B: W* C/ H$ I# Z7 Y0 S
}
- A" A' M- m0 @/ `
CloseHandle(hThread);
5 K: v7 A5 j3 i2 S: N. S
}
V- a% M6 c7 S& v
closesocket(sListen);
* K1 u0 I6 m9 j0 ?$ M1 h a
) F% ?9 g8 `8 i2 x! n& j! Q7 W
WSACleanup();
& [- t7 u( X: |! I4 z- K" ~3 o! V
return 0;
# i0 a1 t0 @' D
}
复制代码
. |2 a- _; C: J0 F, k, v3 ~
, n$ p: q4 `; V/ F) {9 x
" y# T" M6 W: B) ^
: u) c6 c2 k4 x# E7 U a- k
; S. d/ c" N; i9 }
作者:
admin
时间:
2020-5-9 02:16
作为服务器,你要绑定【bind】到本地的IP地址上进行监听【listen】,但是你的机器上可能有多块网卡,也就有多个IP地址,这时候你要选择绑定在哪个IP上面,如果指定为INADDR_ANY,那么系统将绑定默认的网卡【即IP地址】。
& p% B+ ?) A& D+ y
( m" E$ z8 V: b! O- {! w
作为客户端,你要连接【connect】到远端的服务器,也是要指定远端服务器的(ip, port)对。
, B7 M0 ] Z& U4 g- Y
当然,在这种情况下,不可能将IP地址指定为INADDR_ANY,系统会疯掉的。
# X# P; B! p, n8 G" q3 Z3 `
$ n3 A& L$ w' d* y
Server:
/ @8 F! R8 B5 ^% \. j& R
#include <winsock2.h>
" Y7 I" y) t$ u1 M' a5 r- |$ W
#pragma comment(lib, "WS2_32.lib")
+ j5 c9 [. r5 H
) B; {8 c1 `- e8 X; D
#include <stdio.h>
6 ^# g, V0 Y: I: H' R
void main()
1 ?9 \: N5 o& ?' X
{
, g( i: o" R# O' u4 j" S" T
WORD wVersionRequested;//版本号
! D1 Z, {2 o! s6 q' ^' P, y
WSADATA wsaData;
8 A! t* ?. t# W2 g
int err;
G. M8 Y+ _5 @. a1 a3 Q9 }
! @, x% q4 w$ y3 K- U& i$ T) p
wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
2 ~) y% K! K% X6 P. b" X# E
//加载套接字库,如果失败返回
; c: S2 [- J; r: [0 c) o& K
err = WSAStartup(wVersionRequested, &wsaData);
: e# r. u$ n) |/ [! A C+ `
if (err != 0)
8 q& c. t2 i, o. B/ c
{
. G; l3 T1 ^% T( ]/ b }9 V
return;
U0 U4 F! I! l
}
" n, X6 C! p& K# i+ q& ?( b) B
9 G2 r6 t/ M* r
//判断高低字节是不是2,如果不是2.2的版本则退出
& z0 `/ B/ g1 M
if (LOBYTE(wsaData.wVersion) != 2 ||
" J5 e4 z% Y b; J
" D) f: Z( O, _ F/ w5 u
HIBYTE(wsaData.wVersion) != 2)
' L. \) b- }% ?; a! [* E5 i
: I# S' @! y2 }& z
{
' k+ M: P! w. i6 }! p
return;
/ g3 I3 I% g6 U* A2 y9 g0 d+ N
}
+ H4 ]: V# e0 E
8 C8 J% a) b6 h+ z4 k
//创建流式套接字,基于TCP(SOCK_STREAM)
# G% A/ ]: y) _
a: C2 Z9 N2 R2 M3 U
SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);
7 q; }$ a S9 a7 {2 g
( L7 V: j+ M. Z5 U0 E; h: f4 H7 R h
//Socket地址结构体的创建
. R3 X( S6 ~$ Y; Z) d% a
, {$ C& h3 I1 O. t M0 d8 Q
SOCKADDR_IN addrSrv;
; u! C" r- o6 l; z# I
( N v& z/ X' t) r# v
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
, E: H3 J. X' j* U& K, [
addrSrv.sin_family = AF_INET;//指定地址簇
& |! p* i: N9 j$ T, X
addrSrv.sin_port = htons(6000);
3 ]% d- M' e: L" d) o
//指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换
: E1 w- n! W+ L
/ f7 [( S) K7 F6 ~
//将套接字绑定到一个端口号和本地地址上
& b" d% D3 a6 M2 W1 D4 w% v6 E
bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行
. F: e& v7 Q2 A* E* ?7 ?$ ]- e: ?
8 j, J% b7 R/ t
listen(socSrv, 5);
7 U. \8 ~1 b; x1 V7 u$ h+ W
" e) v+ q' |- o8 W1 d. X6 p* h8 F
SOCKADDR_IN addrClient;//字义用来接收客户端Socket的结构体
- Z: k9 I8 }, D7 Z6 [3 j$ j
- Y8 j6 F0 P8 H' t7 o
int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof
0 A- s1 u8 @( G( F8 q) J
3 ]/ z, G' S. Z9 j% q/ n0 D
//循环等待接受客户端发送请求
' v% g/ B0 b0 x4 R& n& t1 E; d
- v; t, }/ @; r; t
while (1)
: B4 Z* l- ~. W2 k
{
0 w/ `1 ]& Q/ C5 D& D
//等待客户请求到来;当请求到来后,接受连接请求,
5 }2 H, ^# G d* q
# ^4 c& R0 O* d. w; U
//返回一个新的对应于此次连接的套接字(accept)。
) F0 v& Q2 |% p) m: Y
//此时程序在此发生阻塞
( K& f# K/ m4 y& y" V4 w
/ k& m4 ]; J# L, a, z5 k
SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len);
4 ?/ w: R% A% s. N+ h
G* U7 m; c' ^6 g& R1 H
char sendBuf[100];
3 G4 c/ p1 t9 B7 u
! S4 ^ i. u% N& Q
sprintf(sendBuf, "Welcome %s to JoyChou",
8 m4 t; A6 Z4 a( V
, W* x" X+ Z! ?0 {4 ]( v
inet_ntoa(addrClient.sin_addr));//格式化输出
, `( J. k. m' o! P
' m% X- ?, h7 Y! J- t
//用返回的套接字和客户端进行通信
( } j: W8 A! i7 P Q" t- q- G
" O- G' s# \% |, P
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多发送一个字节
$ g& ]' N, r1 |5 @* s* [+ c
$ \: c Y3 Y! b7 ?1 _/ D
//接收数据
) A! v9 @! g, e* y0 c
" q% g, n$ v3 [
char recvBuf[100];
1 O+ d# L a% d, X! O& s6 P
1 P4 G* x* w8 d' Y8 W4 G# q
recv(sockConn, recvBuf, 100, 0);
- R6 s: r3 C* Y, H; ~' P
* `5 h v- \: m% K6 @
printf("%s\n", recvBuf);
" K9 f, O! Q) d e3 V
closesocket(sockConn);
, C0 e, K4 p' k9 `
0 T# Z7 [0 w3 f, w$ l1 d8 W
}
6 v" T: p( N2 l* n6 @
}
. |! M; s3 i* m* h
4 a0 i( Y% x$ l# V5 m
9 f% Q" x; R: J: @9 V, Y, a! p
Client:
# l+ ]. R3 z, Y
! A: j6 E. B6 S
#include <winsock2.H>
* c( s a P% `5 X
#pragma comment(lib, "Ws2_32.lib")
- N! q: ~' V) ^1 u- f
#include <stdio.h>
# ^$ S! ?0 f/ h8 A& b
#include <string.h>
1 h+ Q; Y' R8 r
8 ~9 q" d! ?1 v9 O9 c2 ? h
void main()
/ I' k( d+ W- p4 W& T+ N. f0 @& _
{
; U( P8 d2 w1 M/ w6 [4 X* z
WORD wVersionRequested;
) y1 G/ d# Q/ I
WSADATA wsaData;
) N0 R% y) T4 `
int err;
" Z4 o( e" O6 |/ a! e: o: c
. u* L; }2 y, ~. i
wVersionRequested = MAKEWORD( 2, 2 );
+ X ]% |9 }9 m8 ^3 f
0 J, u' V+ @- q; {! J
err = WSAStartup( wVersionRequested, &wsaData );
V; N) m( E# \; T
if ( err != 0 ) {
- l! j% Q% D8 f" c) T% \( }9 E( t; }
+ P9 t0 m8 V7 r. U$ U
return;
; F# g& T. R; `4 G+ u' Z5 O
}
% w! `0 l& ^5 [- ]& m
- z* O+ B$ Z; Z- A1 Y; d
5 n9 D8 t) V/ @: d/ ^2 M+ H2 H) o
if ( LOBYTE( wsaData.wVersion ) != 2 ||
: z3 f. \) v% I. x* R! j, p
HIBYTE( wsaData.wVersion ) != 2 )
, H( c# P4 \6 k/ p2 i
{
$ G" t$ S! L0 m, z. ]6 P6 {8 R
7 k2 o2 |1 o: n
WSACleanup( );
* V) M Z" @# [. o% A6 A" |
return;
/ u9 h: i$ q7 A f$ `' Q
}
) R0 e7 T, K1 v2 }4 C+ Q0 J0 Q
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0);
' D2 B) h y/ U. o9 M" _2 G
SOCKADDR_IN addrSrv;
% H6 u+ U( O: u
addrSrv.sin_family = AF_INET;
' o4 X& A+ p% @3 q. n U# m
addrSrv.sin_port = htons(6000);
6 ~6 W" E5 h; h3 N# {
addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");//服务器端的IP地址
) I0 n4 D2 n! _( P6 G" v1 q L# A' n
% ]# A! ?5 Q' ^! a5 `4 q$ f
connect(socketClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
6 l4 i0 G" [/ m
char recvBuf[256];
0 W5 k+ X/ O, M+ l) x
char sendBuf[] = "This is Joychou";
2 R0 M* I7 k/ y. x% l
recv(socketClient, recvBuf, 256, 0);
$ N+ s8 e( f" T6 C6 b$ w9 }
printf("%s\n", recvBuf);
/ ?& |* M4 i8 Y( ^4 ^3 c7 W1 q* c4 @
send(socketClient, sendBuf, strlen(sendBuf) + 1, 0);
3 ^! {9 Z/ S% j# s! S! p
closesocket(socketClient);
; ]1 s8 j; L8 [
WSACleanup();
( J, v8 r0 X( [, [
1 ~2 I& F/ P8 }( ?
}
复制代码
; ]3 N4 P, t( A! S. ^
1 q+ x/ m5 H0 |' g2 X, h
欢迎光临 cncml手绘网 (http://www.cncml.com/)
Powered by Discuz! X3.2