简介:客户端连接服务器,向服务器发送什么内容,服务器就回客户端什么内容。IP可改。
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <poll.h>
#define PORT 9000
#define FWQIP 0 //IP端口,可改
int main(int argc, char* argv[])
{
int lfd=socket(AF_INET,SOCK_STREAM,0);
struct sockaddr_in seraddr,cliaddr;
seraddr.sin_family=AF_INET;
seraddr.sin_port=htons(PORT);
seraddr.sin_addr.s_addr=FWQIP;
int a=bind(lfd,(struct sockaddr*)&seraddr,sizeof(seraddr));
if(a<0)
{
perror("bind error:");
return 0;
}
listen(lfd,64);
socklen_t len=sizeof(cliaddr);
//定义一个结构体数组
struct pollfd fds[1025];//定义了1025个结构体数组,他比select优势在于他的个数可以由结构体指定,而不是像select一样固定的1024个
int i=0;
for(i=0; i<1025;i++)
{
fds[i].fd=-1;//全部赋值为-1是为了后面好操作。
}
fds[0].fd=lfd;//监听lfd文件描述符
fds[0].events=POLLIN;
int maxfd=0;//在结构体数组中的目前最大下标是0.
while(1)
{
int pollnum= poll(fds, maxfd+1 , -1);//-1表示一直等待,如果没有事件发生他不会返回直接执行下面的语句。fds表示结构体数组
if(pollnum < 0)
{
perror("accpet error:");
// exit(1);
}
else//poll没有出错,监听有没有新的客户机和我连接
{
if(fds[0].revents & POLLIN)//判断lfd的POLLIN事件有没有发生,用&,判断是因为如果不仅仅是POLLIN事件发生了那么用==判断就会出错,这里只>
//没有就执行for语句的数据处理,不加该判断会导致,没有新的连接时阻塞在accept上
{
int cfd=accept(lfd,(struct sockaddr*)&cliaddr,&len);
if(cfd < 0)//表示accept出错
{
perror("accept error:");
// exit(1);
}
else
{
//accept没有出错,解析客户机的IP和端口号
int cliport=ntohs(cliaddr.sin_port);//网络端口号转本地端口号
char det[1025];
inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, det,sizeof(det));//网络IP转本地IP
printf("客户端已连接:IP = %s , 端口号 = %d\n", det , cliport);
//我们要把accept返回的文件描述符即与客户机通信的描述符重新加回到监听行列中
for(i= 1;i < 1025; i++)
{
if(fds[i].fd==-1)//前面初始化时候全部赋值为-1就是为了这里好找到空闲的
{
fds[i].fd=cfd;
fds[i].events=POLLIN;
break;
}
// if(--pollnum ==0 )//表示全部加到监听结构体里面了
// {
// break;
// }为什么不能把这个if语句写在for里面,假如同时间有n个客户机连接我。但是accept一次只能从全连接队列里面取一个出来,你写在for里面看似把所有的客户机的描述符都放进来结构体数组里面,其实结构体数组里面有多个重复的fds[].fd
}
//修改maxfd的值
if(maxfd < i)
{
maxfd = i;
}
if(--pollnum == 0)
{
continue;
}
}
}
//lfd处理完了,现在可以对客户机发送的数据进行处理了。
for( i=1 ; i < maxfd+1; i++)//通过循环的方式,一个一个的去判断POLLIN事件有没有发生
{
if(fds[i].revents & POLLIN)//判断POLLIN事件有没有发生
{
char buf[1024];
int rr=read(fds[i].fd, buf,sizeof(buf));
if(rr==0)
{
printf("客户端断开连接\n");
close(fds[i].fd);
fds[i].fd=-1;
}
if(rr<0)
{
perror("read error:");
exit(1);
}
write(1, buf, rr);
write(fds[i].fd, buf, rr);
if(--pollnum==0)//要么不写这个,要么只能写if(fds[i].revents & POLLIN)的里面
{
break;
}
}
//if(--pollnum==0)
//{
// break;
//}//为什么不能把这个if语句写外面,假如现在只有一个客户端发送了数据,但是这个客户端的描述符可能不是1。但是你每一次都执行了--pollunm就导致了都没有判断到客户端的cfd触发没有呢就break了
}
}
}
return 0;
}