1、多线程网络服务
:多线程网络模式类似于多进程网络模式;不同的是:新客户端到来时,启动的是一个线程(每来一个客户,将创建一个线程)。
模型分析
2、代码实现
同样用处理整数运算来模拟多线程的并发处理
(1)、utili.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>
#define SERVER_PORT 9090
#define SERVER_IP "127.0.0.1"
#define LISTEN_QUEUE 5
#define BUFFER_SIZE 255
typedef
enum
{ADD,SUB,MUL,DIV,MOD, QUIT}OPER_TYPE;
typedef
struct
OperStruct{
int
op1;
int
op2;
OPER_TYPE oper;
}OperStruct;
|
(2)、ser.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
#include"../utili.h"
void
* Thread_Handler(
void
*arg);
void
* Thread_Handler(
void
*arg){
int
sockConn = *(
int
*)arg;
OperStruct op;
int
result;
while
(1){
int
res = recv(sockConn, &op,
sizeof
(op), 0);
if
(res == -1){
printf
(
"recv data fail.\n"
);
continue
;
}
if
(op.oper == ADD){
result = op.op1 + op.op2;
}
else
if
(op.oper == SUB){
result = op.op1 - op.op2;
}
else
if
(op.oper == MUL){
result = op.op1 * op.op2;
}
else
if
(op.oper == DIV){
result = op.op1 / op.op2;
}
else
if
(op.oper == QUIT){
break
;
}
res = send(sockConn, &result,
sizeof
(result), 0);
if
(res == -1){
printf
(
"send data fail.\n"
);
continue
;
}
}
close(sockConn);
pthread_exit(0);
}
int
main(
void
){
int
sockSer = socket(AF_INET, SOCK_STREAM, 0);
if
(sockSer == -1){
perror
(
"socket"
);
return
-1;
}
struct
sockaddr_in addrSer, addrCli;
addrSer.sin_family = AF_INET;
addrSer.sin_port = htons(SERVER_PORT);
addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);
socklen_t len =
sizeof
(
struct
sockaddr);
int
res = bind(sockSer, (
struct
sockaddr*)&addrSer, len);
if
(res == -1){
perror
(
"bind"
);
close(sockSer);
return
-1;
}
listen(sockSer, LISTEN_QUEUE);
int
sockConn;
while
(1){
printf
(
"Server Wait Client Connect.......\n"
);
sockConn = accept(sockSer, (
struct
sockaddr*)&addrCli, &len);
if
(sockConn == -1){
printf
(
"Server Accept Client Connect Fail.\n"
);
continue
;
}
else
{
printf
(
"Server Accept Client Connect Success.\n"
);
printf
(
"Client IP:>%s\n"
, inet_ntoa(addrCli.sin_addr));
printf
(
"Client Port:>%d\n"
,ntohs(addrCli.sin_port));
}
pthread_t tid;
pthread_create(&tid, NULL, Thread_Handler, &sockConn);
}
close(sockSer);
return
0;
}
|
(3)、cli.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
#include"utili.h"
void
InputData(OperStruct *pt);
void
InputData(OperStruct *pt){
printf
(
"please input op1 and op2 : "
);
scanf
(
"%d %d"
, &(pt->op1), &(pt->op2));
}
//Cli
int
main(
void
){
int
sockCli = socket(AF_INET, SOCK_STREAM, 0);
if
(sockCli == -1){
perror
(
"socket"
);
return
-1;
}
struct
sockaddr_in addrSer;
addrSer.sin_family = AF_INET;
addrSer.sin_port = htons(SERVER_PORT);
addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);
socklen_t len =
sizeof
(
struct
sockaddr);
int
res = connect(sockCli, (
struct
sockaddr*)&addrSer, len);
if
(res == -1){
perror
(
"connect"
);
close(sockCli);
return
-1;
}
else
{
printf
(
"Client Connect Server Success.\n"
);
}
char
cmd[2];
OperStruct op;
int
result;
while
(1){
printf
(
"Please input operator : "
);
scanf
(
"%s"
,cmd);
if
(
strcmp
(cmd,
"+"
) == 0){
op.oper = ADD;
InputData(&op);
}
else
if
(
strcmp
(cmd,
"-"
) == 0){
op.oper = SUB;
InputData(&op);
}
else
if
(
strcmp
(cmd,
"*"
) == 0){
op.oper = MUL;
InputData(&op);
}
else
if
(
strcmp
(cmd,
"/"
) == 0){
op.oper = DIV;
InputData(&op);
}
else
if
(
strcmp
(cmd,
"quit"
) == 0){
op.oper = QUIT;
}
else
{
printf
(
"Cmd invalid.\n"
);
}
res = send(sockCli, &op,
sizeof
(op), 0);
if
(res == -1){
printf
(
"send data fail.\n"
);
continue
;
}
if
(op.oper == QUIT)
break
;
res = recv(sockCli, &result,
sizeof
(result), 0);
if
(res == -1){
printf
(
"recv data fail.\n"
);
continue
;
}
printf
(
"result = %d\n"
, result);
}
close(sockCli);
return
0;
}
|
运行结果
服务器端
客户1
客户2
3、分析总结
多线程网络服务也存在线程的动态申请与释放,还是有一定的开销,若存在大量用户在线,很可能带来线程间切换开销。