您的位置:首页 > 理论基础 > 计算机网络

网络并发服务器模型

2011-08-31 08:36 351 查看
TCP并发服务器

流程如下:

sock(...);

bind(...);

listen(...);

while(1){
accept(...);
if(fock() == 0){
while(1){recv(...); process(...); send(...);}
close(...);
exit(...);
}
close(...);

}

demo:

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <signal.h>
#include <stdio.h>

void waitchild(int signaln)
{
wait(NULL);
}

int main(int argc, char *argv[])
{
int server_sock, client_sock;
struct sockaddr_in server_addr, client_addr;
int client_len = sizeof(client_addr);  //注意初始化,不然会有意想不到的错误
int pid;
char buf[128];
int n;

signal(SIGCHLD, waitchild);
if(argc < 2)
{
fprintf(stderr,"usage: %s ip port\n", argv[0]);
exit(-1);
}

if((server_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("fail to socket");
exit(-1);
}

bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = ntohs(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);

if(bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("fail to bind");
exit(-1);
}

listen(server_sock, 5);//server_sock作为监听描述符,如果满足条件(等待队列不为空),即可用accpet返回新的描述符进行通信

printf("listen...\n");

bzero(&client_addr, sizeof(client_addr));
while(1)
{
client_sock = accept(server_sock,(struct sockaddr *)&client_addr, &client_len);

if((pid = fork()) < 0)
{
perror("fail to fork");
exit(-1);
}

if(pid == 0)
{
while(1)
{
memset(buf, 0, sizeof(buf));
n = read(client_sock, buf, sizeof(buf));
write(client_sock, buf, n);
if(strncmp(buf, "quit", 4) == 0)
{
close(client_sock);
exit(1);
}
}
}
close(client_sock);
}

return 0;
}


I/O多路复用并发服务器
流程如下:

初始化(socket -> bind -> listen);

while(1){
设置监听读写文件描述符集合(FD_ *);
调用select;
如果是监听套接字就绪,说明有新的连接请求{
建立连接(accpet);
加入到监听文件描述符集合;
}
否则说明是一个已经连接过的描述符{
进行操作(send 或者 recv);
}

}

demo:

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>

fd_set _rdfs;//selec每次返回就绪的文件描述符状态不变,其他全部清零,所以要用全局变量备份

int main(int argc, char *argv[])
{
int server_sock, client_sock;
struct sockaddr_in server_addr, client_addr;
int client_len = sizeof(client_addr);
int pid;
char buf[128];
int i, n;
int maxfd;
fd_set rdfs;

fd_set _rdfs;

if(argc < 2)
{
fprintf(stderr,"usage: %s ip port\n", argv[0]);
exit(-1);
}

if((server_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("fail to socket");
exit(-1);
}

bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = ntohs(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);

if(bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
{
perror("fail to bind");
exit(-1);
}

listen(server_sock, 5);

printf("listen...\n");

bzero(&client_addr, sizeof(client_addr));

maxfd = server_sock;
FD_ZERO(&_rdfs);
FD_SET(server_sock, &_rdfs);

while(1)
{
rdfs = _rdfs;

select(maxfd+1, &rdfs, NULL, NULL, NULL);//注意select的参数列表

for(i = 0; i <= maxfd; i++)
{
if(FD_ISSET(i, &rdfs))
{
if(i == server_sock)
{
client_sock = accept(server_sock,(struct sockaddr *)&client_addr, &client_len);

FD_SET(client_sock, &_rdfs);
maxfd = client_sock;
maxfd = (client_sock>maxfd)?client_sock:maxfd;
printf("fd_set...\n");
}

else
{
printf("aaaaa\n");
memset(buf, 0, sizeof(buf));
n = read(i, buf, sizeof(buf));
printf("read...\n");
write(i, buf, n);
printf("write...\n");

if(strncmp(buf,"quit", 4) == 0)
{
FD_CLR(i, &_rdfs);
close(i);
}
}
}
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息