在最基本的模型中,服务器一次只处理一个客户端,如果你想要实现一个可以扩展的服务器的话,那么该如何去做呢
最简单的扩展方式是为每个客户端产生一个新的线程,但不推荐这种方式,因为:
1.线程比较难以编码,调试,而且有些时候,它们会产生不可预测的结果
2.切换上下文的消耗
3.对于大量的客户端,不可扩展
4.可能会引起死锁
Select()
使用Linux中的select命令
1.select命令允许监控多个file descriptors, 等待其中一个file descriptor可用
2.如果sockets中有一个要提供信息,select命令将会提供信息
3.Select就像中断处理那样工作,当如果有file descriptor传递信息时使用
slect使用的数据结构是 fd_set, 这包含了一个活动要监视的所有file descriptor,主要的方法有四个
fd_set readfds;
//Clear an fd_set
FD_ZERO(&readfds);
//Add a descriptor to an fd_set
FD_SET(master_sock, &readfds);
//Remove a descriptor from an fd_set
FD_CLR(master_sock, &readfds);
//If something happened on the master socket, then its an incoming connection
FD_ISSET(master_sock, &readfds);
实现代码:
#include <stdio.h>
#include <string.h> //strlen
#include <stdlib.h>
#include <errno.h>
#include <unistd.h> //close
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/sockets.h>
#include <netinet/in.h>
#include <sys/time.h> //FD_SET FD_ISSET, FD_ZERO macros
#define TRUE 1
#define FALSE 0
#define PORT 8888
int main(int argc, char * argv[]) {
int opt = TRUE;
int master_socket, addrlen, new_socket, client_socket[30], max_clients = 30, activity, i, valread, sd;
int max_sd;
struct sockaddr_in address;
char buffer[1025];
//set of socket descriptors
fd_set readfds;
//a message
char *message = "ECHO Daemon v1.0 \r\n";
//初始化所有client_socket为0
for(i=0; i<max_clients;i++) {
client_socket[i] = 0;
}
if( (master_socket = socket(AF_INET, SOCK_STREAM, 0 )
网友评论