#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MYPORT 1234 // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
#define BUF_SIZE 10
int fd_A[BACKLOG]; // accepted connection fd
int conn_amount; // current connection amount
void err(char
*s)
{
printf("%s\n", s);
exit(0);
}
void set_fl(int fd, int flags)
{
int val;
if((val = fcntl(fd, F_GETFL, 0)) < 0)
err("fcntl");
val |= flags;
if((val = fcntl(fd, F_SETFL, val)) < 0)
err("fcntl2");
}
int main(void)
{
int sock_fd, new_fd; // listen on
sock_fd, new connection on new_fd
struct sockaddr_in server_addr; // server address information
struct sockaddr_in client_addr; // connector's address information
socklen_t sin_size;
int yes = 1;
char buf[BUF_SIZE];
int ret;
int i;
if((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err("socket");
if(setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0)
err("setsockopt");
server_addr.sin_family
= AF_INET;
// host byte order
server_addr.sin_port
= htons(MYPORT); // short,
network byte order
server_addr.sin_addr.s_addr = INADDR_ANY; // automatically fill with my IP
memset(server_addr.sin_zero,
'\0', sizeof(server_addr.sin_zero));
if(bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
err("bind");
if(listen(sock_fd, BACKLOG) <
0)
err("listen");
printf("listen port %d\n",
MYPORT);
fd_set fdsr;
int maxsock;
struct timeval tv;
conn_amount = 0;
sin_size = sizeof(client_addr);
maxsock = sock_fd;
while(1)
{
// initialize file
descriptor set
FD_ZERO(&fdsr);
FD_SET(sock_fd, &fdsr);
// timeout setting
tv.tv_sec = 30;
tv.tv_usec = 0;
// add active
connection to fd set
for(i = 0; i < BACKLOG; i++)
{
if(fd_A[i] != 0)
{
FD_SET(fd_A[i], &fdsr);
}
}
ret = select(maxsock + 1, &fdsr, NULL, NULL, &tv);
printf("\nselect\n");
if(ret < 0)
{
err("select");
}
else if(ret == 0)
{
printf("timeout\n");
continue;
}
// check every fd in
the set
for (i = 0; i < conn_amount; i++)
{
if(FD_ISSET(fd_A[i], &fdsr))
{
while(1)
{
errno = 0;
ret = recv(fd_A[i], buf, sizeof(buf) - 1, 0);
if(ret < 0)
{
if(errno == EAGAIN)
{
printf("EAGAIN\n");
break;
}
else
{
printf("may not be happen\n");
break;
}
}
else if(ret == 0)
{
printf("client[%d] close\n",
i);
close(fd_A[i]);
FD_CLR(fd_A[i], &fdsr);
fd_A[i] = 0;
break;
}
else
{
// receive data
buf[ret] = 0;
printf("client[%d] send:%s\n",
i, buf);
}
}
}
}
// check whether a
new connection comes
if(FD_ISSET(sock_fd,
&fdsr))
{
new_fd =
accept(sock_fd,
(struct sockaddr
*)&client_addr, &sin_size);
if(new_fd <= 0)
err("accept");
set_fl(new_fd, O_NONBLOCK);
// add to fd queue
if(conn_amount < BACKLOG)
{
fd_A[conn_amount++] = new_fd;
printf("new connection client[%d] %s:%d\n", conn_amount -1,
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if(new_fd > maxsock)
maxsock =
new_fd;
}
else
{
printf("max connections arrive, exit\n");
send(new_fd, "bye", 4, 0);
close(new_fd);
break;
}
}
}
// close other
connections
for(i = 0; i < BACKLOG; i++)
{
if(fd_A[i] != 0)
{
close(fd_A[i]);
}
}
exit(0);
}
|