cncml手绘网
标题:
一个简单的C语言的socket服务器和客户端程序
[打印本页]
作者:
admin
时间:
2020-5-9 02:14
标题:
一个简单的C语言的socket服务器和客户端程序
程序很简单,windows环境下的,客户端和服务器程序都在本机运行,在客户端输入发送给服务器的字符串,服务器收到字符串后会打印出来,同时与"abc"比较,与"abc"相同就会返给客户端,输入的是正确的,不同会告诉客户端输入时错误的。
, Y" B+ s- R( w9 s' @
客户端程序:client.cpp
( z5 X9 w. W0 I8 I
#include <winsock2.h>
! f( y" M1 r4 H8 l
#include <stdio.h>
) J- v" q2 F, X+ k2 B2 D. h0 P
#include <stdlib.h>
7 N. m. o" d, C" z) v8 ~. {
' B4 H+ S6 l* m( A
#define DEFAULT_PORT 5150
9 M4 z& I- I5 `6 z: Q
#define DEFAULT_BUFFER 2048
" A/ H: I0 J0 A% l
8 X! I- |" l1 B3 H' N7 a) C# d% U
char szServer[128],
2 q! i3 ]5 Q0 h4 L
szMessage[1024];
% A1 N2 A. b2 v0 E, w: l
int iPort = DEFAULT_PORT;
6 m+ \7 U/ U8 t
2 h: q1 t) ~2 a
int main()
$ W7 ]+ }+ C7 f4 k4 f0 L
{
. u2 s; P$ W( n" u
WSADATA wsd;
! T6 a9 t8 M; M1 ^5 [, H* y1 k$ _
SOCKET sClient;
* A7 B! I: h- ^( t$ Y
char szBuffer[DEFAULT_BUFFER];
; N! j( s" {8 f
int ret;
7 I; a' s+ R2 R) q' x8 `( f
struct sockaddr_in server;
: `) u. I+ w2 [4 ^; ]; ?
struct hostent *host = NULL;
% [ y/ S2 f2 H# V4 x3 f# ]* \5 j
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
* j9 X7 S1 F/ V2 S6 i
{
y: {) \7 y/ F, @ U
printf("Failed to load Winsock library!\n");
, j# k X; u9 M( i( d
return 1;
1 V$ u4 F: v( u- M& x& k
}
- k3 |' I$ c8 b, ~" f# Y' o! r
printf("Enter a string to send to server:\n");
. `* i; b6 C0 j5 z( ?2 w* U
gets(szMessage);
7 r. |1 [$ H/ ?; O8 A
// Create the socket, and attempt to connect to the server
& V' j$ o3 E0 B1 u8 K/ C3 ^( z
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
9 j& v4 H( o# [0 S/ b( b
if (sClient == INVALID_SOCKET)
3 P# r O7 G7 e" v- e2 {
{
4 ~1 l$ u' g1 \9 r
printf("socket() failed: %d\n", WSAGetLastError());
. [8 b6 }* R! u7 Z
return 1;
. |2 |+ T: L# y: w, y4 o
}
. Y, A+ f/ c" r5 L
server.sin_family = AF_INET;
* U( W$ h2 T0 S: q
server.sin_port = htons(iPort);
5 ?' k9 U) Z% C3 [9 a) Z5 a
server.sin_addr.s_addr = inet_addr("127.0.0.1");
2 y3 P& S' w* u' J
3 x8 h7 c" _. a9 ~/ E3 X& Q
if (connect(sClient, (struct sockaddr *)&server,
3 ?- p6 y( x- x. H0 l" i; t7 H
sizeof(server)) == SOCKET_ERROR)
% ~* l$ y. m9 \$ w# U0 S
{
% J `) {$ \$ L8 C) ]$ {
printf("connect() failed: %d\n", WSAGetLastError());
- H; g; G6 N. A O- Z" J
return 1;
7 a' F* ` J6 C8 y U- V
}
9 W( R4 l/ K# e/ t- I
// Send and receive data
4 j, {' G% R. _6 o
ret = send(sClient, szMessage, strlen(szMessage), 0);
: i2 [' ?& I! z. }* g
if (ret == SOCKET_ERROR)
+ ], O$ D& W; `5 o
{
' C1 w, w( H0 b \" ?% D2 `
printf("send() failed: %d\n", WSAGetLastError());
# u2 T4 I( b' ^' h* Y
}
1 `8 M' k0 D& C1 v3 y0 Q$ ~
else{
1 u, a7 h3 S' ?" G# Z
printf("Send '%s' \n", szMessage);
5 k( v5 p8 U' r% x$ G+ z3 Q. v; i
ret = recv(sClient, szBuffer, DEFAULT_BUFFER, 0);
. j% C- T) E4 A
if (ret == SOCKET_ERROR){
3 H& ~, }# e- s4 z0 r
printf("recv() failed: %d\n", WSAGetLastError());
) B0 { q' b" V: ]" L
}
3 ^9 D; Y- e5 X
else{
1 h1 r9 j s ~8 q: O
szBuffer[ret] = '\0';
2 z* B" N" u0 j3 d
printf("RECV: '%s'\n",szBuffer);
. C, G+ Q$ U9 R' M2 r+ J, A. c. \
}
3 n5 Z' Q4 @( o2 t% l$ z H C! p( i
}
5 l( a6 X& ?' }- n: \
closesocket(sClient);
9 j J2 Z% p% l. `7 T4 U
- q: E# v; g; ^6 n# g; H% a
WSACleanup();
. X; G: S8 O& {) s
return 0;
* [5 F9 s" I# ~( J8 u2 \) B
}
复制代码
服务器程序:server.cpp
( @9 T$ V+ A: j" T6 r4 ]* ]) X
#include <winsock2.h>
; \" W! ?4 J0 Z' p" W( @8 z
#include <stdio.h>
. o" X2 z3 D( D7 e% D3 c3 |4 u
#include <stdlib.h>
: q6 k0 N1 z4 ]! t
4 S) t( o& u. W& `: ] Z e( P
#define DEFAULT_PORT 5150
& Y3 V! T! Y0 \8 L, }8 [! D& z
#define DEFAULT_BUFFER 4096
6 b) o: N2 j+ g* s) J# }
9 f( M/ T0 N. @- N* \
int iPort = DEFAULT_PORT;
9 K! U0 I. f# b# X
char szAddress[128];
& @1 u l; r* K' _8 G
' |" i, C; @) ~
DWORD WINAPI ClientThread(LPVOID lpParam)
/ R/ B: ?$ O. E# S
{
* O0 |$ z7 U8 x
SOCKET sock=(SOCKET)lpParam;
- y% C6 f1 M8 q6 B
char szBuff[DEFAULT_BUFFER];
8 V! A! X6 t# |, E
int ret;
; l9 _ k( h# S5 z% x
- D- q# V. `: b L1 J% B4 ^, M
while(1)
3 J2 ?- F- X1 S! @/ i) ~
{
1 T4 N1 q* z% Q9 f; |" s+ p% x
ret = recv(sock, szBuff, DEFAULT_BUFFER, 0);
- Y1 Q$ W" Y S, z
if (ret == 0)
" Y: P! Z, h: `2 R5 Z* V
break;
5 I# J& M9 J; b) ~% f3 h
else if (ret == SOCKET_ERROR)
3 ^! ?1 Z/ K" o' R" W M0 ~% d
{
! H* x' B& i) E. F# A
printf("recv() failed: %d\n", WSAGetLastError());
# D8 F. v* X8 o4 \# n
break;
) q3 u# _& D$ o0 i; q
}
) X% R5 t/ T& k1 {' ?0 e" i
szBuff[ret] = '\0';
# C1 P+ Q% x g) O4 f1 y
printf("RECV: '%s'\n", szBuff);
0 t; K, r7 O! }& F5 n
if(strcmp(szBuff,"abc")==0){
% w- U2 f4 ~# b
memcpy(szBuff,"Send the correct string!",25);
; H" L6 H. }% n+ W
}
; f5 N$ [' c6 [' s: i
else{
3 a# Z7 G; H0 m: `% q5 w1 c
memcpy(szBuff,"Send the wrong string!",23);
+ w" R5 i2 A# J8 O3 E- {
}
% n: ~; ?# i# ^! S
ret = send(sock, szBuff, strlen(szBuff), 0);
8 E) G7 z# g6 Q+ _1 B# B
if (ret == SOCKET_ERROR){
9 i- T. u7 O8 V: B. F
printf("send() failed: %d\n", WSAGetLastError());
/ o1 j$ V' J) J* ^
}
% k# U9 D% E( M
}
. b" m/ z3 M: _4 O0 o9 @" |
return 0;
- N$ z& e: S2 ?6 q. t% Q; e; H7 E
}
: i. b$ Z+ J$ m) h% X
4 b$ h8 Q6 X. T8 T y: i* g
int main()
, L' t8 y+ J- N, g; B m
{
% f- x; P! M% C# H0 {, }( F
WSADATA wsd;
) v5 _' V0 n! y- ]/ e3 W5 N; k
SOCKET sListen,
/ A0 Z5 h D4 d: G/ Z; z
sClient;
2 c" i) b B6 M8 p
int iAddrSize;
% p( \$ C5 s; S1 G9 a. F: O( I
HANDLE hThread;
i4 Q; O! ~! Q8 i
DWORD dwThreadId;
/ M& h0 a5 I& N+ f, S x* y. Q8 M
struct sockaddr_in local,
2 z7 I- w$ R4 W" a: q
client;
& _ K9 i- r' p; o4 H0 n, a7 o
6 T, F4 E% M& M! j: f+ J' l& U
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
( k. P( L7 I2 N% u* O
{
- {& t8 k) z7 [1 j
printf("Failed to load Winsock!\n");
0 z+ L8 E& ?6 w1 {7 I: r7 O% |
return 1;
1 T4 G& J' G% ?$ R
}
3 t* G: M! M5 r1 L
// Create our listening socket
1 l2 U# B" `2 h* y. ^
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
/ z9 F$ H2 |! I& V5 a
if (sListen == SOCKET_ERROR)
: F3 V* N t( S" G4 f. I
{
0 v: I! ^1 R3 t; u. s( k
printf("socket() failed: %d\n", WSAGetLastError());
% j* v; R' a* h; n1 O/ ]- g
return 1;
6 C1 q. q3 a4 n- q5 p. q
}
- A8 p, d6 B" P$ m- O ^
local.sin_addr.s_addr = htonl(INADDR_ANY);
% a+ X( M- p* @* n1 K. P, V7 y# w" W
local.sin_family = AF_INET;
2 [" }, B( | ]& b7 N- q$ `' Q
local.sin_port = htons(iPort);
: g$ w! o6 Q; O
% }/ F$ C; X5 ]: _% l
if (bind(sListen, (struct sockaddr *)&local,
3 z& c3 G0 ^* t3 z
sizeof(local)) == SOCKET_ERROR)
. K) m; C3 i- k @2 x+ W
{
( R+ y% s6 \, N) t/ h! X3 R2 I# _
printf("bind() failed: %d\n", WSAGetLastError());
- E# ?) I4 N* j, E. I
return 1;
4 x" t) _3 L6 o+ ~$ S! N9 `
}
+ `! r9 Z+ u6 B% t
listen(sListen, 8);
$ z8 Q* H4 o$ Q
// In a continous loop, wait for incoming clients. Once one
5 }3 r# j- Q! C \5 R3 V4 D6 `4 B
// is detected, create a thread and pass the handle off to it.
, u$ A- B6 C! I
while (1)
' g9 b; V* G& T7 x7 R/ F, i" [, ]
{
( C! e6 I# U% H8 M
iAddrSize = sizeof(client);
: p+ q( M6 p. R( I9 V" I# t
sClient = accept(sListen, (struct sockaddr *)&client,
1 [( s( x9 t2 b
&iAddrSize);
! h: l& t. U1 u; Z
if (sClient == INVALID_SOCKET)
3 L! P5 K# c- B' {5 c9 m, D
{
- F1 J1 x- f d- i( {9 C0 \
printf("accept() failed: %d\n", WSAGetLastError());
& k$ ?; I& `) ~6 x* G0 s' J
break;
: u4 Y# n6 Q" l' }, D8 h
}
1 q7 Y6 |, A: R- I4 E
printf("Accepted client: %s:%d\n",
; z& w+ t4 x, u/ Y5 l
inet_ntoa(client.sin_addr), ntohs(client.sin_port));
4 ~% F" o; Z' x* U# U
" b+ e0 V5 @5 \" x+ X7 w/ F* W
hThread = CreateThread(NULL, 0, ClientThread,
@. {3 Y1 v; [
(LPVOID)sClient, 0, &dwThreadId);
8 S- |" g$ m/ J% L
if (hThread == NULL)
* w0 X* S, Y/ W* ~' b
{
0 Z; B p* M* ^6 `- m) Q
printf("CreateThread() failed: %d\n", GetLastError());
% R- s! {) ~% D0 R! K; ] b9 b
break;
- z6 p# ~4 D8 J: U* l# r% q
}
( f( ^, ^4 W+ P; ~7 @1 U
CloseHandle(hThread);
7 J" O% h7 r$ x! m0 h7 L8 q
}
/ Q2 n& q& ?% i* u' U
closesocket(sListen);
, ~6 U$ j& X3 k/ b& N! z
* L6 Z6 }) Q% B; C9 E- P- O
WSACleanup();
8 }; L9 S' i9 w- P
return 0;
- y* t5 @$ e# j- s- E' X
}
复制代码
. W. r* y0 a" @. t c
; `8 N" z% Z% ^6 q6 \3 M" r" m
, i1 X p @, `+ y
- d" [% [# w" o' [4 q! E. b! ?
$ J# @% `1 `% O" n" D
作者:
admin
时间:
2020-5-9 02:16
作为服务器,你要绑定【bind】到本地的IP地址上进行监听【listen】,但是你的机器上可能有多块网卡,也就有多个IP地址,这时候你要选择绑定在哪个IP上面,如果指定为INADDR_ANY,那么系统将绑定默认的网卡【即IP地址】。
6 k* s* S& C# g5 ?
5 W6 m! t( J- |- F$ e' t
作为客户端,你要连接【connect】到远端的服务器,也是要指定远端服务器的(ip, port)对。
$ j0 R8 |4 }2 T0 K
当然,在这种情况下,不可能将IP地址指定为INADDR_ANY,系统会疯掉的。
. L& G# E& r+ F1 G
b1 p/ \; y) h7 M- o0 X
Server:
3 o! Q$ w3 m! n! O7 D* C" U! D3 l0 ]
#include <winsock2.h>
$ Z: d$ m% k$ f y
#pragma comment(lib, "WS2_32.lib")
( L4 W- ?% Y& Q
7 z+ L( ~& L- A: Q6 {) V; J
#include <stdio.h>
5 r; S9 l2 P3 ^. s
void main()
% u' C6 x6 n2 H& A. F8 F% u6 _
{
# N# ~5 C" x! Y8 L, d
WORD wVersionRequested;//版本号
: I" j" R6 O, M
WSADATA wsaData;
) ]4 L% l0 @6 G3 H+ D1 F4 h
int err;
9 P, c. d. e6 e& I7 P
. [ Y4 h+ u$ H# h$ J- ^* |
wVersionRequested = MAKEWORD(2, 2);//2.2版本的套接字
& ~2 y- N6 i; h' B# F8 f
//加载套接字库,如果失败返回
4 w. c, n4 ]4 [. a. q/ @2 {
err = WSAStartup(wVersionRequested, &wsaData);
8 d5 Z$ s+ {; j( t
if (err != 0)
& c" ]2 Q( k( R6 M4 A: q
{
1 n5 Q. q K5 Q7 h8 t2 j! m
return;
, `, m, O7 N( U& t
}
! d& \" K7 a7 J, w( a+ j
) x B8 O* D$ t. A' d8 X8 Z
//判断高低字节是不是2,如果不是2.2的版本则退出
8 y3 o; K- J& k
if (LOBYTE(wsaData.wVersion) != 2 ||
) m4 s. H2 m) d+ `& W
. f0 K/ @1 ^, q. w. E( V. x
HIBYTE(wsaData.wVersion) != 2)
2 O1 F% |- d; m5 S$ z
7 d- V: o8 m0 m$ f' u
{
; a- k F& P7 G- ]7 U y
return;
$ y8 a, w/ U1 q: W- B" k/ L& P
}
. |4 {- }$ u3 j% R, n
) _, }& u: t. J% O1 J# e/ n7 f
//创建流式套接字,基于TCP(SOCK_STREAM)
: ?/ J8 ]( L$ L9 }2 z( ^1 A
$ d1 i( F! A9 ~ X) i
SOCKET socSrv = socket(AF_INET, SOCK_STREAM, 0);
9 b% }& Q4 `9 T- \5 p3 B
8 ^% W/ p5 I" ~4 i
//Socket地址结构体的创建
: g' t q. T1 u9 k0 X$ V
! v' T' w; ]% m' o
SOCKADDR_IN addrSrv;
3 Y1 m, o6 a( F4 d* O. M6 G
- Z% V8 q3 @% l) Y! K- ~
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//转换Unsigned long型为网络字节序格
d2 Y. ?" r3 u8 j+ G& ?5 T
addrSrv.sin_family = AF_INET;//指定地址簇
( E. z( w2 \, O9 X {5 T
addrSrv.sin_port = htons(6000);
1 g8 B/ k5 t4 M
//指定端口号,除sin_family参数外,其它参数都是网络字节序,因此需要转换
% |0 a( z- b- o8 s, @
/ F$ r$ x2 @) _! k2 o$ y
//将套接字绑定到一个端口号和本地地址上
( J2 q( o% C" K Q% ]" l" a
bind(socSrv, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//必须用sizeof,strlen不行
, w6 o" B/ S# G- n9 [" z
% c+ N) S5 w2 \4 i/ c) X0 t
listen(socSrv, 5);
% Y4 L. f( H5 F; O# e& w2 @1 K) c
) x' x$ ?* J' P* d0 n
SOCKADDR_IN addrClient;//字义用来接收客户端Socket的结构体
) L. y9 t8 M* z5 D) }& k
; S0 f G# D. }! _$ M$ q% z; t
int len = sizeof(SOCKADDR);//初始化参数,这个参数必须进行初始化,sizeof
2 x* E* |8 m, D
( l2 G+ i! s. t# } K& j- q
//循环等待接受客户端发送请求
3 f! Z* C- d# ~1 Z* @) W
2 J8 l$ m7 p8 X, ~8 B Y
while (1)
& Q. C6 d! K$ }! I$ Y5 G" }; v& L# g0 _
{
+ K! B( \) ^9 f A4 a5 L/ K/ \ m
//等待客户请求到来;当请求到来后,接受连接请求,
/ e+ \7 O! X8 `9 z1 X
2 u) g( T0 E7 H. M# O
//返回一个新的对应于此次连接的套接字(accept)。
7 p' M/ B4 y0 [( Y* N2 f
//此时程序在此发生阻塞
* f3 o0 ~( c- }. d
9 ^9 [$ ^- M' n
SOCKET sockConn = accept(socSrv, (SOCKADDR*)&addrClient, &len);
* u8 W2 g( q! z6 |& ^& M/ K9 \5 `
; k$ }/ Z! H) M3 s
char sendBuf[100];
: d7 B `& W! h7 U' ]
4 S' d% U1 f' R& v- |
sprintf(sendBuf, "Welcome %s to JoyChou",
1 \4 a8 P1 _9 _* h. Z& g" h* I
]( r+ ]( Z" I: k0 Z) v% b. z
inet_ntoa(addrClient.sin_addr));//格式化输出
5 F4 p6 W# i' I
) a, {+ b# @- c! [3 T
//用返回的套接字和客户端进行通信
$ v9 Y$ f6 Q9 I
. |2 |0 H/ h0 k) {) y& V: ~: \6 P# ]
send(sockConn, sendBuf, strlen(sendBuf)+1, 0);//多发送一个字节
, [- t' E; Z* v9 g! Q4 w
% A, V7 O: j. @1 X; x
//接收数据
: J H- D% O* r2 T g, m8 M
' ^8 F3 v- Y# j3 t6 ^, O
char recvBuf[100];
% t$ t! D# ` B
# C/ H9 G8 q- u* |
recv(sockConn, recvBuf, 100, 0);
# q/ M, U) C* x; F6 H3 i3 m
; l' q$ W; g3 P! \' i
printf("%s\n", recvBuf);
& A# D5 F; j0 d; A# M) B
closesocket(sockConn);
, c& ~8 Q: Y4 H+ ?, P. X
, k. K" b. {% ], i
}
7 T6 C9 z/ n2 A5 B/ T% y1 x
}
) O1 D& Z0 w9 i# x
) |$ a9 Y- k) ?$ ]# M
f. B% O1 c4 v7 ]
Client:
9 b6 W9 | i( f$ o2 P+ { ^
( [1 d/ \8 T& p
#include <winsock2.H>
1 ^7 R: E) }4 i+ B- ^: i
#pragma comment(lib, "Ws2_32.lib")
5 k- m; `3 U3 l9 B# Q. Z) G5 J! z
#include <stdio.h>
2 U; S, T) X# ]! m! s
#include <string.h>
8 A5 G/ Z2 k5 Y: d
3 B7 H# D' u j, d f7 D% z
void main()
9 K6 _- s; _7 K
{
$ O) m' \9 R* v4 F% |# N1 @& Z
WORD wVersionRequested;
9 s/ p( c# B9 [8 b
WSADATA wsaData;
+ H+ Q" f; f( @" Q- Z5 Y4 p
int err;
& J! L& g" e: B7 @* y
) u0 s6 E8 c$ o$ @1 M
wVersionRequested = MAKEWORD( 2, 2 );
2 o ?3 ?- \- Y% S& [( x) Z7 P# V
* f* c' W5 R+ F7 @3 b. e6 K% M! S
err = WSAStartup( wVersionRequested, &wsaData );
3 k- I7 \$ u, a' i
if ( err != 0 ) {
' }( q3 h) E' c! |/ W5 n* h1 ^
: n4 h* w o8 ^9 }
return;
/ l$ f8 l2 R2 [$ l8 Z
}
]! ?+ \ Z( ^
: a' m# m6 }* i# P6 {5 r/ N
9 v5 d, ^/ Y: Q' i! N7 k
if ( LOBYTE( wsaData.wVersion ) != 2 ||
+ V! A: B7 M2 B- n) u
HIBYTE( wsaData.wVersion ) != 2 )
& |! V+ y! ^. R, Z
{
( f4 N7 u1 T% @* a
/ J5 R: g7 L3 I7 W7 z; c1 Y
WSACleanup( );
3 c, k- v. G) T' d
return;
, _" d$ q8 E2 }+ t8 F0 q
}
8 K2 q- ]" [) N; I; n+ ]3 F1 w
SOCKET socketClient = socket(AF_INET, SOCK_STREAM, 0);
6 d) Y/ ^7 t, q+ n f
SOCKADDR_IN addrSrv;
4 M% n6 c* z9 U" l" h
addrSrv.sin_family = AF_INET;
! W( u6 B% s E
addrSrv.sin_port = htons(6000);
W) j' l) H4 ^6 H) z
addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.101");//服务器端的IP地址
' W) Y1 u, y; r1 ~6 U' M8 u
; o4 m' ?7 g- e: U. E2 z* t! o
connect(socketClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
8 y* \( a1 }) \; B- _7 {
char recvBuf[256];
& z/ D8 R; T# @+ s d; @
char sendBuf[] = "This is Joychou";
9 @$ n3 x# s( n4 X) M1 Q: s
recv(socketClient, recvBuf, 256, 0);
" z( S) l! k4 H; \5 c( v
printf("%s\n", recvBuf);
8 v) d2 I5 K" u6 O: U
send(socketClient, sendBuf, strlen(sendBuf) + 1, 0);
6 a. z9 S4 l9 _7 G/ T" ^6 d/ |" E
closesocket(socketClient);
& w2 K2 U- e) e( N% m
WSACleanup();
! e- A, `$ {' x* `8 i: L
: [& _! `3 a' S# R6 L
}
复制代码
5 J# s0 U$ ^- c [
9 f- h3 U9 V( A1 S
欢迎光临 cncml手绘网 (http://cncml.com/)
Powered by Discuz! X3.2