//util.h
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/time.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<poll.h>
#define backlogs 10
#define BUF_SIZE 50
int Socket(int domain,int type,int protocol)
{
int fd=socket(domain,type,protocol);
if(fd==-1)
return -1;
return fd;
}
int Bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen)
{
int ret=bind(sockfd,addr,addrlen);
if(ret==-1)
return -1;
return ret;
}
int Listen(int sockfd,int backlog)
{
int ret=listen(sockfd,backlog);
if(ret==-1)
return -1;
return ret;
}
int start_up(const char* ip,int port)
{
int fd=Socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in ser_addr;
ser_addr.sin_family=AF_INET;
ser_addr.sin_port=htons(port);
ser_addr.sin_addr.s_addr=inet_addr(ip);
int on=1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int));
socklen_t addrlen=sizeof(struct sockaddr);
Bind(fd,(struct sockaddr*)&ser_addr,addrlen);
Listen(fd,backlogs);
return fd;
}
#include"util.h"
#define OPEN_MAX 1024
int main(int argc,char *argv[])
{
int i,n,j,maxi;
int nready; //接收poll返回值,记录满足监听事件的fd个数
struct pollfd client[OPEN_MAX];//1024
int sockfd,listenfd,connfd;
char buf[BUF_SIZE];
char str[INET_ADDRSTRLEN];//16
struct sockaddr_in cliaddr,servaddr;
socklen_t clilen;
listenfd=start_up(argv[1],atoi(argv[2]));
client[0].fd=listenfd;//要监听的第一个文件描述符 存入client[0]中
client[0].events=POLLIN;//listenfd监听普通读事件
for(i=1;i<OPEN_MAX;i++)
client[i].fd=-1; //用-1初始化client[]里剩下元素
maxi=0;
while(1)
{
nready=poll(client,maxi+1,-1); //阻塞监听是否有客户端连接
if(client[0].revents & POLLIN) //listenfd有读事件就绪
{
clilen=sizeof(struct sockaddr);
connfd=accept(listenfd,(struct sockaddr*)&cliaddr,&clilen);//accept()不会阻塞
printf("Receive from %s at PORT %d\n",inet_ntop(AF_INET,&cliaddr,str,sizeof(str)),
ntohs(cliaddr.sin_port));
for(i=1;i<OPEN_MAX;i++)
{
if(client[i].fd==-1)
client[i].fd=connfd;//找到client[]中空闲的位置,存放accept()返回的connfd
break;
}
if(i==OPEN_MAX) //达到客户端最大连接数
printf("Too many clients!!!,The Ser is load!!!\n");
client[i].events=POLLIN; //设置刚刚返回的connfd 监听读事件
if(i>maxi)
maxi=i; //更新client[]最大元素下标
if(--nready==0) //没有更多就绪事件时,继续回到poll阻塞
continue;
}
for(i=1;i<=maxi;i++) //检测client[] 查看哪个connfd就绪 即要读数据
{
if( (sockfd=client[i].fd)<0)
continue;
if(client[i].revents & POLLIN)
{
int recv_byte=recv(sockfd,buf,sizeof(buf)+1,0);
if(recv_byte<0)
{
perror("recv error!\n");
continue;
}
else if(recv_byte==0)//说明客户端关闭连接
{
printf("client[%d] close connection!!!\n",i);
close(sockfd);
client[i].fd=-1;
}
else
{
for(j=0;j<recv_byte;j++)
buf[j]=toupper(buf[j]);
send(sockfd,buf,128,0);
}
if(--nready<=0)
break;
}
}
}
}
//客户端 cli.c
#include"util.h"
int main(int argc,char *argv[])
{
char sendbuf[128];
char recvbuf[128];
socklen_t addrlen=sizeof(struct sockaddr);
int cli_fd=socket(AF_INET,SOCK_STREAM,0);
if(cli_fd==-1)
return -1;
struct sockaddr_in seraddr;
seraddr.sin_family=AF_INET;
seraddr.sin_port=htons(atoi(argv[2]));
seraddr.sin_addr.s_addr=inet_addr(argv[1]);
int ret=connect(cli_fd,(struct sockaddr*)&seraddr,addrlen);
if(ret==-1)
{
perror("connect error!\n");
return -1;
}
else
printf("success\n");
while(1)
{
printf("Cli:>");
scanf("%s",sendbuf);
send(cli_fd,sendbuf,strlen(sendbuf)+1,0);
recv(cli_fd,recvbuf,128,0);
printf("From Self Cli:%s\n",recvbuf);
}
close(cli_fd);
return 0;
}