select web

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>

#define MAX_FD 1024

typedef struct{
int fd;
short state; /*0 read, 1 write */

}conn_fd_desc_t;

conn_fd_desc_t connFdArr[MAX_FD];
int connSize;
int maxFd;

int createListenFd(){
char addr_p[16];

int port = 3001;
char *ip ="172.18.63.83";

struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);

int listenfd = socket(PF_INET, SOCK_STREAM, 0);

int opt = SO_REUSEADDR;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); /*设置socket属性*/

int ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address) );

if (ret != 0){
fprintf(stderr, "bind error:%s\n", error(errno));
fprintf(stderr, "bind rslt=%d\n", ret);

}

ret = listen(listenfd, 5);

printf("listen rslt=%d\n", ret);

maxFd = listenfd;

return listenfd;
}

int get_conn_arr_free_index(){
int i;
for (i = 0; i < MAX_FD; i++)
if (connFdArr[i].fd == -1)
return i;

return -1;
}


int setnonblocking(int fd){
int old_option = fcntl(fd, F_GETFL);
int new_option = old_option | O_NONBLOCK;
fcntl(fd, F_SETFL, new_option);
return old_option;
}

void set_sel_events( fd_set *readSet, fd_set *writeSet, fd_set *expSet){

int i;

FD_ZERO(readSet);
FD_ZERO(expSet);
FD_ZERO(writeSet);

for (i = 0; i < MAX_FD; i++)
if (connFdArr[i].fd != -1){
if ( 0 == connFdArr[i].state)
FD_SET(connFdArr[i].fd, readSet);
else if (1 == connFdArr[i].state)
FD_SET(connFdArr[i].fd, writeSet);
else
FD_SET(connFdArr[i].fd, expSet);

}
}

void readFromFd(int index){
int ret;
char buf[1024];

int count = 0;
int fd = connFdArr[index].fd;

while(1){
memset(buf, 0x00, sizeof(buf) );
ret = recv(fd, buf, sizeof(buf)-1, 0);
if (ret < 0){
if ((errno == EAGAIN) || (errno==EWOULDBLOCK) ){
return ;
}
else{
connFdArr[index].fd = -1;
connFdArr[index].state = -1;
fprintf(stderr, "fd[%d] closed by client\n", fd);
break;
}
}
else if (0 == ret){
connFdArr[index].fd = -1;
connFdArr[index].state = -1;
fprintf(stderr, "fd[%d] closed by client\n ");

return;
}

printf("%s", buf);
count += ret;
}
if (count > 0){
printf("get %d bytes of normal data\n", count);
}
}

int loopServie(int listenfd){
int sel_fd_arr[MAX_FD];
/*
-1 indicate not in use
0 flags in use
*/
int i;
for (i = 0; i < MAX_FD; i++){
connFdArr[i].fd = -1;
connFdArr[i].state = -1;
}
connSize = 0;
fd_set readSet, writeSet, expSet;
FD_ZERO(&readSet);
FD_ZERO(&expSet);
FD_ZERO(&writeSet);

struct sockaddr_in client_address;
socklen_t client_addrlength = sizeof(client_address);


FD_SET(listenfd, &readSet);
connFdArr[connSize].fd = listenfd;
connFdArr[connSize].state = 0;
maxFd = listenfd;

int count = 1;
while(1){
int max = maxFd;

/*invocation using blocking mode */

fprintf(stderr, "select for %d times\n", count);
int ret = select(max+1, &readSet, &writeSet, &expSet, NULL);
if (ret < 0){
printf("selection failure \n");
continue;
}

count++;

fprintf(stderr, "select return %d\n", ret);


for (i = 0; i < MAX_FD +1; i++){

int sel_fd = connFdArr[i].fd;
if (FD_ISSET(sel_fd, &readSet)){
if (sel_fd == listenfd){/* new connection arrives */
int connfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addrlength);
char addr_p[16];
memset(addr_p, 0x00, sizeof(addr_p) );
printf("connection from %s \n", inet_ntop(AF_INET, &client_address.sin_addr, addr_p, sizeof(addr_p)));
if ( connfd < 0){
printf("errno is %d\n", errno);
close(listenfd);
return -1;
}
if (connfd > maxFd)
maxFd = connfd;

FD_SET(listenfd, &readSet);
FD_CLR(listenfd, &writeSet);
FD_CLR(listenfd, &expSet);

int idx = get_conn_arr_free_index();
assert(idx != -1);

connFdArr[idx].fd = connfd;
connFdArr[idx].state = 0;
setnonblocking(connfd);
FD_SET(connfd, &readSet);
FD_CLR(connfd, &writeSet);
FD_CLR(connfd, &expSet);

fprintf(stderr, "connfd is [%d]\n", connfd);
}
else{
fprintf(stderr, "read data from fd [%d]\n", sel_fd);
/*read data from network*/
readFromFd(i) ;
FD_SET(sel_fd, &writeSet);
FD_CLR(sel_fd, &readSet);
FD_CLR(sel_fd, &expSet);
}
}
else if (FD_ISSET(sel_fd, &writeSet)){

fprintf(stderr, "write data into fd [%d]\n", i);

char buf[1024];
memset(buf, 0x00, sizeof(buf) );

sprintf(buf, "HTTP/1.1 200 OK\r\n");
sprintf(buf+strlen(buf), "Content-Type: text/html;charset=ISO-8859-1\r\n");
sprintf(buf+strlen(buf), "Content-Length: 122\r\n");
sprintf(buf+strlen(buf), "Connection: Keep-Alive\r\n");

sprintf(buf+strlen(buf), "\r\n");
sprintf(buf+strlen(buf), "<html><head><title>Wrox Homepage</title></head><body> body goes here</body></html>");

write(sel_fd, buf, sizeof(buf));

connFdArr[i].state = 1;
FD_SET(sel_fd, &readSet);
FD_CLR(sel_fd, &writeSet);
FD_CLR(sel_fd, &expSet);
}
else if( FD_ISSET(sel_fd, &expSet) ){
fprintf(stderr, "error state \n");
connFdArr[i].fd = -1;
}
}

//set_sel_events(sel_fd_arr, &readSet, &writeSet, &expSet);

}

return 0;
}

int main(int argc ,char *argv[]){

int listenfd = createListenFd();


loopServie(listenfd);

sleep(20);
close(listenfd);

return 0;

}

posted @ 2016-06-06 18:36  Andy.gbhu  阅读(167)  评论(0)    收藏  举报