/* 采用链表来保存【连接socket】 */
#include "wrap.h"
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <strings.h>
#define SRV_PORT 2222
#define LISTEN_BACKLOG 128
#define CLIENT_MAXSIZE 1024
struct cfd_node{
uint connfd;
struct cfd_node* next;
};
struct cfd_node* head=NULL;
int main(int argc,char* argv[]){
uint lfd,cfd,max_fd;
struct cfd_node* ptr,*preptr;
char buf[BUFSIZ];
struct sockaddr_in srv_addr,client_addr;
socklen_t client_addr_len,srv_addr_len;
char client_ip_addr[20];
lfd=Socket(AF_INET,SOCK_STREAM,0);
max_fd=lfd;
srv_addr_len=sizeof(srv_addr);
init_sockaddr_in((struct sockaddr*)&srv_addr,srv_addr_len,AF_INET,SRV_PORT,INADDR_ANY);
Bind(lfd,(struct sockaddr*)&srv_addr,srv_addr_len);
int opt=1;
setsockopt(lfd,SOL_SOCKET,SO_REUSEPORT,&opt,sizeof(opt)); /* 多路复用 */
Listen(lfd,LISTEN_BACKLOG);
fd_set rset,allset; /* 读集合,备份集合 */
FD_ZERO(&allset);
FD_SET(lfd,&allset);
while(1){
rset=allset;
int sel_ret=Select(max_fd+1,&rset,NULL,NULL,NULL);
printf("Listen success! current fd num:%d\n",sel_ret);
if(sel_ret>0){
if(FD_ISSET(lfd,&rset)){
client_addr_len=sizeof(client_addr);
cfd=Accept(lfd,(struct sockaddr*)&client_addr,&client_addr_len);
FD_SET(cfd,&allset);
/* 头插法 */
struct cfd_node* node=malloc(sizeof(struct cfd_node));
node->connfd=cfd;
node->next=head;
head=node;
printf("new client coming! ip: %s port %d \n",
inet_ntop(AF_INET,&client_addr.sin_addr.s_addr,client_ip_addr,sizeof(client_ip_addr))
,ntohs(client_addr.sin_port));
max_fd=(cfd>max_fd?cfd:max_fd);
if(sel_ret==1) continue;
}
#ifdef SIMPLE
/* 数据处理-轮询 */
for(int connfd=lfd+1;connfd<max_fd+1;connfd++){
printf("work!\t");
if(FD_ISSET(connfd,&rset)){
int n=Read(connfd,buf,sizeof(buf));
if( n == 0){
printf("connect close!\n");
Close(connfd);
FD_CLR(connfd,&allset);
}else if(n>0){
printf("%d bytes data coming!\n",n);
Write(STDOUT_FILENO,buf,n);
for(int j=0;j<n;j++){
buf[j]=toupper(buf[j]);
}
Write(connfd,buf,n);
}
}
}
#else
/* 链表轮询 */
ptr=head;
preptr=NULL;
while(ptr!=NULL){
int connfd=ptr->connfd;
if(FD_ISSET(connfd,&rset)){
int n=Read(connfd,buf,sizeof(buf));
if( n == 0){
printf("connect close!\n");
Close(connfd);
FD_CLR(connfd,&allset);
/* 链表中删除失效socket */
if(preptr==NULL){//头结点
head=ptr->next;
}
else if(ptr->next!=NULL){
preptr->next=ptr->next;
}
free(ptr);
}else if(n>0){
Write(STDOUT_FILENO,buf,n);
for(int j=0;j<n;j++){
buf[j]=toupper(buf[j]);
}
Write(connfd,buf,n);
}
}
preptr=ptr;
ptr=ptr->next;
}
#endif
}
}
return 0;
}