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;
}

浙公网安备 33010602011771号