select实现tcp并发服务器的基本框架流程
2013-11-18 15:11
681 查看
服务端初始化:
socket();
bind();
listen();
for( ; ; )
{
FD_SET(listen_fd , &allset);//设置监听读写文件描述符
select();//调用select函数
if()//如果是倾听套接字就绪,说明一个新的连接请求建立
{
建立连接(accept);
加入到监听文件描述符中去;
}
else//否则说明是一个已经连接过的描述符
{
进行操作(read或者write);
}
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <pthread.h>
#define SERV_PORT 9888
#define WAIT_COUNT 5
#define READ_SIZE 32
//void send_myself(int fd);
//void *pthread_handle(void *arg);
int main(int argc, char **argv)
{
pthread_t tid;
int i,max_i,listen_fd,max_fd,conn_fd,sock_fd;
int nready,client[FD_SETSIZE];
fd_set allset;
struct sockaddr_in listen_addr,client_addr;
socklen_t len = sizeof(struct sockaddr_in);
listen_fd = socket(PF_INET,SOCK_STREAM,0);
if(listen_fd == -1)
{
perror("socket failed !");
return -1;
}
max_i = -1;
max_fd = listen_fd;
bzero(&listen_addr,sizeof(listen_addr));
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listen_addr.sin_port = htons(SERV_PORT);
bind(listen_fd,(struct sockaddr *)&listen_addr,len);
listen(listen_fd,WAIT_COUNT);
for(i = 0; i < FD_SETSIZE; ++i)
client[i] = -1;
FD_ZERO(&allset);
for(;;)
{
FD_SET(listen_fd,&allset);
nready = select(max_fd+1,&allset,NULL,NULL,NULL);
if(FD_ISSET(listen_fd,&allset))
{
len = sizeof(struct sockaddr);
conn_fd = accept(listen_fd,(struct sockaddr *)&listen_addr,&len);
if(conn_fd == -1)
{
perror("accept fail !");
return -1;
}
for(i = 0; i < FD_SETSIZE; ++i)
{
if(client[i] < 0)
{
client[i] = conn_fd;
break;
}
}
if(FD_SETSIZE == i)
{
perror("too many clients!");
return -1;
}
FD_SET(conn_fd,&allset);/*add new descriptor to allset*/
if(conn_fd > max_fd)
max_fd = conn_fd;
if(i > max_i)
max_i = i;
if(--nready <= 0)
continue;
}
else
{
for(i = 0; i <= max_i; ++i)/*check all clients for data*/
{
if((sock_fd = client[i]) < 0)
continue;
if(FD_ISSET(sock_fd,&allset))
{
//int *lptr = (int*)malloc(sizeof(int));
//*lptr = sock_fd;
//int err = pthread_create(&tid,NULL,pthread_handle,lptr);
//send_myself(sock_fd);
char tmp[READ_SIZE] = {0};
int size = read(sock_fd,tmp,READ_SIZE-1);
write(STDOUT_FILENO,tmp,size);
bzero(tmp,READ_SIZE);
FD_CLR(sock_fd,&allset);
close(sock_fd);
client[i] = -1;
continue;
//if(--nready <= 0)
//break;
}
}
}
}
return 0;
}
/*
void *pthread_handle(void *arg)
{
int connfd = *((int*)arg);
free(arg);
pthread_detach(pthread_self());
send_myself(connfd);
close(connfd);
return NULL;
}
*/
/*
void send_myself(int fd)
{
char tmp[READ_SIZE] = {0};
char *p_tmp = tmp;
while(1)
{
int size = read(fd, tmp,READ_SIZE-1);
write(STDOUT_FILENO,tmp,size);
if(0 == size)
{
perror("read fail!");
return;
}
if(0 == write(fd,tmp,size))
{
perror("write client failed !");
return;
}
bzero(tmp,READ_SIZE);
}
}
*/
socket();
bind();
listen();
for( ; ; )
{
FD_SET(listen_fd , &allset);//设置监听读写文件描述符
select();//调用select函数
if()//如果是倾听套接字就绪,说明一个新的连接请求建立
{
建立连接(accept);
加入到监听文件描述符中去;
}
else//否则说明是一个已经连接过的描述符
{
进行操作(read或者write);
}
}
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <errno.h>
#include <strings.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/time.h>
#include <pthread.h>
#define SERV_PORT 9888
#define WAIT_COUNT 5
#define READ_SIZE 32
//void send_myself(int fd);
//void *pthread_handle(void *arg);
int main(int argc, char **argv)
{
pthread_t tid;
int i,max_i,listen_fd,max_fd,conn_fd,sock_fd;
int nready,client[FD_SETSIZE];
fd_set allset;
struct sockaddr_in listen_addr,client_addr;
socklen_t len = sizeof(struct sockaddr_in);
listen_fd = socket(PF_INET,SOCK_STREAM,0);
if(listen_fd == -1)
{
perror("socket failed !");
return -1;
}
max_i = -1;
max_fd = listen_fd;
bzero(&listen_addr,sizeof(listen_addr));
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
listen_addr.sin_port = htons(SERV_PORT);
bind(listen_fd,(struct sockaddr *)&listen_addr,len);
listen(listen_fd,WAIT_COUNT);
for(i = 0; i < FD_SETSIZE; ++i)
client[i] = -1;
FD_ZERO(&allset);
for(;;)
{
FD_SET(listen_fd,&allset);
nready = select(max_fd+1,&allset,NULL,NULL,NULL);
if(FD_ISSET(listen_fd,&allset))
{
len = sizeof(struct sockaddr);
conn_fd = accept(listen_fd,(struct sockaddr *)&listen_addr,&len);
if(conn_fd == -1)
{
perror("accept fail !");
return -1;
}
for(i = 0; i < FD_SETSIZE; ++i)
{
if(client[i] < 0)
{
client[i] = conn_fd;
break;
}
}
if(FD_SETSIZE == i)
{
perror("too many clients!");
return -1;
}
FD_SET(conn_fd,&allset);/*add new descriptor to allset*/
if(conn_fd > max_fd)
max_fd = conn_fd;
if(i > max_i)
max_i = i;
if(--nready <= 0)
continue;
}
else
{
for(i = 0; i <= max_i; ++i)/*check all clients for data*/
{
if((sock_fd = client[i]) < 0)
continue;
if(FD_ISSET(sock_fd,&allset))
{
//int *lptr = (int*)malloc(sizeof(int));
//*lptr = sock_fd;
//int err = pthread_create(&tid,NULL,pthread_handle,lptr);
//send_myself(sock_fd);
char tmp[READ_SIZE] = {0};
int size = read(sock_fd,tmp,READ_SIZE-1);
write(STDOUT_FILENO,tmp,size);
bzero(tmp,READ_SIZE);
FD_CLR(sock_fd,&allset);
close(sock_fd);
client[i] = -1;
continue;
//if(--nready <= 0)
//break;
}
}
}
}
return 0;
}
/*
void *pthread_handle(void *arg)
{
int connfd = *((int*)arg);
free(arg);
pthread_detach(pthread_self());
send_myself(connfd);
close(connfd);
return NULL;
}
*/
/*
void send_myself(int fd)
{
char tmp[READ_SIZE] = {0};
char *p_tmp = tmp;
while(1)
{
int size = read(fd, tmp,READ_SIZE-1);
write(STDOUT_FILENO,tmp,size);
if(0 == size)
{
perror("read fail!");
return;
}
if(0 == write(fd,tmp,size))
{
perror("write client failed !");
return;
}
bzero(tmp,READ_SIZE);
}
}
*/
相关文章推荐
- Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- 使用Select I/O模型来实现一个并发处理多个客户端的TCP服务器
- 服务器编程入门(11)TCP并发回射服务器实现 - 单线程select实现
- Select I/O模型来实现一个并发处理多个客户端的TCP服务器 <转>
- 基于WSAEventSelect模型的TCP服务器实现
- Linux下两种TCP网络服务器实现方式:循环服务&并发服务
- select实现高并发服务器
- linux下使用select I/O复用和多线程编程实现简单的TCP服务器
- 几种并发服务器模型的实现:多线程,多进程,select,poll,epoll
- C#SocketAsyncEventArgs实现高效能多并发TCPSocket通信 (服务器实现)
- Linux网络编程:TCP服务器(单进程多用户),使用select方法实现
- TCP套接字编程实现简单的并发服务器
- go实现一个简单的游戏服务器框架(lotou)基本设计
- Linux网络编程:TCP服务器(单进程多用户),使用select方法实现
- Linux网络编程——tcp并发服务器(I/O复用之select)
- Linux网络编程——tcp并发服务器(epoll实现)
- 使用select系统调用实现简单的TCP服务器
- 【原创】TCP Socket 简单练习 --- 线程池实现并发服务器 分类: Linux --- 应用程序设计 2014-12-25 13:59 50人阅读 评论(0) 收藏
- Linux网络编程——tcp并发服务器(poll实现)
- Linux C——TCP并发服务器客户端(线程实现)