1、简介
在服务器端,主程序提前构建多个子进程,当客户端的请求到来时,系统从进程池中选取一个子进程来处理客户端的链接,每个子进程处理一个客户端的请求。在全部子进程的处理能力得到满足之前,服务器的网络负载是基本不变的。
此类服务器的一个难点是如何确定进程池中子进程的数量。因为子进程的数量在客户端连接之前已经构造好了,不能进行扩展。
2、tcp模型
3、服务器端源代码(concurrency-server1.c):
- #include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <errno.h>
-
#include <sys/socket.h>
-
#include <arpa/inet.h>
-
#include <netinet/in.h>
-
#include <sys/types.h>
-
#include <unistd.h>
-
#include <time.h>
-
-
#define BUFLEN 1024
-
#define PIDNUM 3
-
-
/*******************并发服务器模型之一:预先分配好了进程的个数**********************/
-
-
static void handle_fork(int sockfd){
-
int newfd;
-
struct sockaddr_in c_addr;
-
char buf[BUFLEN];
-
socklen_t len;
-
time_t now;
-
while(1){
-
len = sizeof(struct sockaddr);
-
if((newfd = accept(sockfd,(struct sockaddr*) &c_addr, &len)) == -1){
-
perror("accept");
-
exit(errno);
-
}else
-
printf("\n*****************通信开始***************\n");
-
printf("正在与您通信的客户端是:%s: %d\n",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port));
-
-
/******处理客户端请求*******/
-
bzero(buf,BUFLEN);
-
len = recv(newfd,buf,BUFLEN,0);
-
if(len >0 && !strncmp(buf,"TIME",4)){
-
bzero(buf,BUFLEN);
-
/*获取系统当前时间*/
-
now = time(NULL);
-
/*ctime将系统时间转换为字符串,sprintf使转化后的字符串保存在buf*/
-
sprintf(buf,"%24s\r\n",ctime(&now));
-
//******发送系统时间*******/
-
send(newfd,buf,strlen(buf),0);
-
}
-
/*关闭通讯的套接字*/
-
close(newfd);
-
}
-
}
-
-
int main(int argc, char **argv)
-
{
-
int sockfd;
-
struct sockaddr_in s_addr;
-
unsigned int port, listnum;
-
pid_t pid[PIDNUM];
-
-
/*建立socket*/
-
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
-
perror("socket");
-
exit(errno);
-
}else
-
printf("socket create success!\n");
-
/*设置服务器端口*/
-
if(argv[2])
-
port = atoi(argv[2]);
-
else
-
port = 4567;
-
/*设置侦听队列长度*/
-
if(argv[3])
-
listnum = atoi(argv[3]);
-
else
-
listnum = 3;
-
/*设置服务器ip*/
-
bzero(&s_addr, sizeof(s_addr));
-
s_addr.sin_family = AF_INET;
-
s_addr.sin_port = htons(port);
-
if(argv[1])
-
s_addr.sin_addr.s_addr = inet_addr(argv[1]);
-
else
-
s_addr.sin_addr.s_addr = INADDR_ANY;
-
/*把地址和端口帮定到套接字上*/
-
if((bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr))) == -1){
-
perror("bind");
-
exit(errno);
-
}else
-
printf("bind success!\n");
-
/*侦听本地端口*/
-
if(listen(sockfd,listnum) == -1){
-
perror("listen");
-
exit(errno);
-
}else
-
printf("the server is listening!\n");
-
/*处理客户端的连接*/
-
int i = 0;
-
for(i = 0; i < PIDNUM; i++){
-
pid[i] = fork();
-
if(pid[i] == 0)
-
handle_fork(sockfd);
-
}
-
/*关闭服务器的套接字*/
-
close(sockfd);
-
return 0;
-
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in s_addr;
unsigned int port, listnum;
pid_t pid[PIDNUM];
/*建立socket*/
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket");
exit(errno);
}else
printf("socket create success!\n");
/*设置服务器端口*/
if(argv[2])
port = atoi(argv[2]);
else
port = 4567;
/*设置侦听队列长度*/
if(argv[3])
listnum = atoi(argv[3]);
else
listnum = 3;
/*设置服务器ip*/
bzero(&s_addr, sizeof(s_addr));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(port);
if(argv[1])
s_addr.sin_addr.s_addr = inet_addr(argv[1]);
else
s_addr.sin_addr.s_addr = INADDR_ANY;
/*把地址和端口帮定到套接字上*/
if((bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr))) == -1){
perror("bind");
exit(errno);
}else
printf("bind success!\n");
/*侦听本地端口*/
if(listen(sockfd,listnum) == -1){
perror("listen");
exit(errno);
}else
printf("the server is listening!\n");
/*处理客户端的连接*/
int i = 0;
for(i = 0; i < PIDNUM; i++){
pid[i] = fork();
if(pid[i] == 0)
handle_fork(sockfd);
}
/*关闭服务器的套接字*/
close(sockfd);
return 0;
}
4、客户端源代码(concurrency-client.c):
- #include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <errno.h>
-
#include <sys/socket.h>
-
#include <arpa/inet.h>
-
#include <netinet/in.h>
-
#include <sys/types.h>
-
#include <unistd.h>
-
#include <time.h>
-
-
#define BUFLEN 1024
-
-
int main(int argc, char **argv)
-
{
-
int sockfd;
-
struct sockaddr_in s_addr;
-
socklen_t len;
-
unsigned int port;
-
char buf[BUFLEN];
-
-
/*建立socket*/
-
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
-
perror("socket");
-
exit(errno);
-
}else
-
printf("socket create success!\n");
-
-
/*设置服务器端口*/
-
if(argv[2])
-
port = atoi(argv[2]);
-
else
-
port = 4567;
-
/*设置服务器ip*/
-
bzero(&s_addr, sizeof(s_addr));
-
s_addr.sin_family = AF_INET;
-
s_addr.sin_port = htons(port);
-
if (inet_aton(argv[1], (struct in_addr *)&s_addr.sin_addr.s_addr) == 0) {
-
perror(argv[1]);
-
exit(errno);
-
}
-
/*开始连接服务器*/
-
if(connect(sockfd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr)) == -1){
-
perror("connect");
-
exit(errno);
-
}else
-
printf("conncet success!\n");
-
-
/******缓冲区清零*******/
-
bzero(buf,BUFLEN);
-
strcpy(buf,"TIME");
-
/******发送消息*******/
-
send(sockfd,buf,strlen(buf),0);
-
/******缓冲区清零*******/
-
bzero(buf,BUFLEN);
-
/******接收消息*******/
-
len = recv(sockfd,buf,BUFLEN,0);
-
if(len > 0)
-
printf("服务器的系统时间是:%s\n",buf);
-
-
-
/*关闭连接*/
-
close(sockfd);
-
-
return 0;
-
}
5、编译源代码:
new@new-desktop:~/linux/c$ gcc -Wall concurrency-server1.c -o server
new@new-desktop:~/linux/c$ gcc -Wall concurrency-client.c -o client
6、运行就ok了,试试吧!
client_mainint main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in s_addr;
socklen_t len;
unsigned int port;
char buf[BUFLEN];
/*建立socket*/
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket");
exit(errno);
}else
printf("socket create success!\n");
/*设置服务器端口*/
if(argv[2])
port = atoi(argv[2]);
else
port = 4567;
/*设置服务器ip*/
bzero(&s_addr, sizeof(s_addr));
s_addr.sin_family = AF_INET;
s_addr.sin_port = htons(port);
if (inet_aton(argv[1], (struct in_addr *)&s_addr.sin_addr.s_addr) == 0) {
perror(argv[1]);
exit(errno);
}
/*开始连接服务器*/
if(connect(sockfd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr)) == -1){
perror("connect");
exit(errno);
}else
printf("conncet success!\n");
/******缓冲区清零*******/
bzero(buf,BUFLEN);
strcpy(buf,"TIME");
/******发送消息*******/
send(sockfd,buf,strlen(buf),0);
/******缓冲区清零*******/
bzero(buf,BUFLEN);
/******接收消息*******/
len = recv(sockfd,buf,BUFLEN,0);
if(len > 0)
printf("服务器的系统时间是:%s\n",buf);
/*关闭连接*/
close(sockfd);
return 0;
}
5、编译源代码:
gcc -Wall concurrency-server1.c -o server
gcc -Wall concurrency-client.c -o client
6、运行就ok了,试试吧!
阅读(2546) | 评论(2) | 转发(2) |