自学嵌入式linux时间也不短了,但是作为一个三天打鱼两天晒网的人来说,我学习随意性很强,一般在工作之余看一点儿书、敲几行代码,进度也很慢。现在把总结的一些内容整理成博客,一方面跟大家共同分享一下学习过程,另一方面呢也督促一下自己努力学习!哈哈。下面进入正题,这篇博客的主题是select()函数实现并发服务器。下面直接上代码(带有注释的哦,全是我自己的理解,有误之处恳请各位大牛多多扶持),在代码的最后我用visio做了个简单的流程图,做的很粗糙,希望不会有碍观瞻!
以下代码是select()函数实现并发服务器的程序代码,现对其作出解释:
#include
#include
#include
#include
#include
#include
#include
#include
#define BACK_LOG 10
#define BUF_SIZE 1024
#define PORT 8000
int main(int argc, char *argv[])
{
int sockfd;
int connfd;
int clifd;
int ret_val;
int max_fd;
int i;
int nready;
int max_index;
int len;
socklen_t clilen;
int port;
struct sockaddr_in servaddr,cliaddr;
int client[FD_SETSIZE];
char buffer[BUF_SIZE];
fd_set allset,rdset;
struct timeval tv = {0, 0};
if(argc != 2)
{
printf("Usage: echoserv ");
exit(1);
}
bzero(&servaddr,sizeof(struct sockaddr_in));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
// servaddr.sin_port = htons(PORT);
servaddr.sin_port = htons(atoi(argv[1])); // 端口号由程序运行时作为参数传入
sockfd = socket(AF_INET, SOCK_STREAM, 0); // 打开通讯端口
if (sockfd == -1)
{
perror("socket");
exit(1);
}
ret_val = bind(sockfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)); //绑定服务器IP和端口
if (ret_val == -1)
{
perror("bind");
exit(1);
}
ret_val = listen(sockfd, BACK_LOG); // 将主动连接套接字变为被动连接套接字
if (ret_val == -1)
{
perror("listen");
exit(1);
}
max_fd = sockfd;
FD_ZERO(&allset); // 清空描述符集
FD_ZERO(&rdset);
FD_SET(sockfd,&allset); // 将通讯端口描述符加入描述符集中
for(i=0; i< FD_SETSIZE; i++)
client = -1;
max_index = -1;
for(;;)
{
rdset = allset;
//nready = select(max_fd+1,&rdset,NULL,NULL,NULL); // 以阻塞方式监听rdset描述符集中是否有可读的描述符
nready = select(max_fd+1,&rdset,NULL,NULL,&tv); // 以完全非阻塞方式监听rdset描述符集中是否有可读的描述符
if(FD_ISSET(sockfd, &rdset)) // FD_ISSET用来检测描述符集中指定描述符状态是否发生了变化,在此用来检测通讯端口是否有新的请求连接
{
clilen = sizeof(cliaddr);
connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &clilen); // 为新建立的连接分配通讯描述符
if(connfd ==-1)
{
perror("accept");
continue;
}
for(i=0; i;>
{
if(client == -1)
{
client = connfd; // 填充客户端通讯描述符表
break;
}
}
if(i == FD_SETSIZE) // FD_SETSIZE宏是在哪里定义的?
{
printf("Too many client here!");
exit(1);
}
if(i > max_index)
max_index = i;
if(connfd > max_fd)
max_fd = connfd;
FD_SET(connfd,&allset);
if(--nready <=0) // 完成对新建的客户端分配描述符之后重新跳select()监控新建立的客户端或者接收已建立客户端的数据发送请求
continue;
}
for (i=0; i<= max_index; i++) // 程序运行到此处说明有客户端发送数据请求(select()函数以阻塞方式工作时)以轮询方式服务已建立的客户端
{
if((clifd=client)< 0)
continue;
if(FD_ISSET(clifd,&rdset)) // 检查是哪个客户端发起的数据请求,并为服务
{
len = BUF_SIZE;
len = recv(clifd, buffer, len, 0);
if (len <= 0)
{
close(clifd);
FD_CLR(clifd,&allset);
client = -1;
}
else
send(clifd,buffer,len,0); // 应用层协议在此实现 ,该范例仅原样返回接收到的字符串
if(--nready <=0)
break;
}//if
}//for
}//for
}
以下是我编写的程序流程图:
用户1585841 2013-5-29 13:47
用户1406868 2013-5-27 18:56
用户1585841 2012-12-21 09:37
用户1674793 2012-12-10 16:35
需要制作蓝牙端在血压测量器上,通过蓝牙端发到iphone/pc上是么?