/*************************************************************************
* Copyright (C): 1540999272@qq.com
* Filename: server.c
* Author: Lu Zengmeng
* Description:
* Creat Time: 2016-07-19 12:08
************************************************************************/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#define PORT 8003
#define BUF_LEN 128
#define BACKLOG 5
int main(int argc, char *argv[])
{
int sock_fd;
int conn_fd;
int yes = 1;
struct sockaddr_in my_addr;
bzero(&my_addr,sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr = INADDR_ANY;
if (-1 == (sock_fd = socket(AF_INET, SOCK_STREAM, 0)))
{
perror("socket");
exit(1);
}
if (-1 == setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)))
{
perror("setsockopt");
exit(1);
}
if (-1 == bind(sock_fd, (struct sockaddr *)&my_addr, sizeof(my_addr)))
{
perror("bind");
exit(1);
}
if (-1 == listen(sock_fd, BACKLOG))
{
perror("listen");
exit(1);
}
printf("listenning...\n");
fd_set fds; //创建select所要检查的集合fds
int max_fd;
int ret;
int i;
int conn_amount = 0;
int fd_all[BACKLOG]= {0,}; //用来存放需要通信的多个socket描述符
struct timeval tv;
char recv_buf[BUF_LEN];
max_fd = sock_fd;
while(1)
{
FD_ZERO(&fds); //初始化关注列表
FD_SET(sock_fd,&fds); //将listen的sock_fd加入关注
tv.tv_sec = 5;
tv.tv_usec = 0;
for(i=0;i<BACKLOG;i++) //将所有需要通信的socket描述符存入fd_all数组
{
if(fd_all[i] != 0)
FD_SET(fd_all[i],&fds);
}
ret = select(max_fd+1,&fds,NULL,NULL,&tv);
if(ret < 0)
{
perror("select");
break;
}
else if(0 == ret)
{
printf("timeout\n");
continue;
}
for(i=0;i<conn_amount;i++)
{
if(FD_ISSET(fd_all[i],&fds)) //检查已建立的连接是否有数据请求
{
ret = recv(fd_all[i],recv_buf,BUF_LEN,0);
if(ret <= 0)
{
printf("client[%d] closed \n",fd_all[i]);
close(fd_all[i]);
FD_CLR(fd_all[i],&fds); //清除已关闭的socket描述符
fd_all[i] = 0;
//conn_amount--;
}
else
{
recv_buf[ret] = '\0';
fflush(stdout);
printf("%s from client[%d]\n",recv_buf,fd_all[i]);
}
}
}
if(FD_ISSET(sock_fd,&fds)) //检查是否有连接请求
{
conn_fd = accept(sock_fd,NULL,NULL);
if( conn_fd < 0)
{
perror("accept");
continue;
}
if(conn_amount < BACKLOG)
{
fd_all[conn_amount++] = conn_fd; //将新建立的连接加入关注
printf("new connection client[%d] \n",conn_fd);
if(conn_fd > max_fd) //重新设置max_fd
max_fd = conn_fd;
}
else
{
printf("max connections arrive,exit\n");
close(conn_fd);
break;
}
}
printf("Client amount: %d\n",conn_amount);
for(i=0;i<BACKLOG;i++)
{
if(fd_all[i]!=0)
printf("client[%d] \n",fd_all[i]);
}
printf("\n");
}
for(i=0;i<BACKLOG;i++)
{
if(fd_all[i] != 0)
close(fd_all[i]); //关闭所有fd
}
return 0;
}
socket编程之select多路复用
最新推荐文章于 2023-06-19 11:15:08 发布