多线程网络服务

1、多线程网络服务

  :多线程网络模式类似于多进程网络模式;不同的是:新客户端到来时,启动的是一个线程(每来一个客户,将创建一个线程)。

模型分析

wKiom1fkln7QEzPYAAAkKjy264I682.png-wh_50

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;
}

运行结果

服务器端

wKioL1fkmzbgrLxbAABN107FgbY468.png-wh_50

客户1

wKiom1fkm36jhRHaAAAkSZGP3kI979.png-wh_50

客户2

wKiom1fkm63wXfyrAAArhiR8FnM399.png-wh_50

3、分析总结

  多线程网络服务也存在线程的动态申请与释放,还是有一定的开销,若存在大量用户在线,很可能带来线程间切换开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值