poll函数在处理并发时, 无FD_SETSIZE限制
//服务器端
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>//使用signal函数
#include <sys/wait.h>//使用wait函数
#include <poll.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE);\
}while(0)
//读确定大小的包
//ssize_t有符号数,size_t为无符号数
ssize_t readn(int fd, void *buf, size_t count)
{
size_t nleft=count;//剩余字节数
ssize_t nread;//已经接受的字节数
char *bufp = (char*)buf;//
while(nleft>0)
{
if((nread=read(fd, bufp, nleft))<0)
{
if(errno==EINTR)//信号中断
{
continue;
}
return -1;//否则出错
}
else if(nread==0)//表示对方关闭传送
{
return count-nleft;//返回已读字节数
}
bufp+=nread;//进行指针偏移
nleft -= nread;
}
return count;
}
ssize_t writen(int fd, const void *buf, size_t count)
{
size_t nleft=count;//剩余字节数
ssize_t nwritten;//已经写入的字节数
char *bufp = (char*)buf;//
while(nleft>0)
{
if((nwritten=write(fd, bufp, nleft))<0)
{
if(errno==EINTR)//信号中断
{
continue;
}
return -1;//否则出错
}
else if(nwritten==0)
{
continue;
}
bufp+=nwritten;//进行指针偏移
nleft -= nwritten;
}
return count;
}
ssize_t recv_peek(int sockfd, void *buf,size_t len)
{
while(1)
{
//recv函数只用于套接口
//recv函数读取后,不将数据在缓冲区清除
int ret= recv(sockfd, buf, len, MSG_PEEK);
if(ret == -1 && errno == EINTR)
continue;
return ret;
}
}
ssize_t readline(int sockfd, void *buf, size_t maxline)
{
int ret;//设置窥探返回值
int nread;//设置已窥探字符数
char *bufp = (char*)buf;//缓存buf
int nleft = maxline;//设置maxline为包最大长度,nleft为剩余需读取字符数
while(1)
{
ret=recv_peek(sockfd, bufp, nleft);
if(ret<0)
{
return ret;
}
else if(ret=0)
{
return ret;//对方终止了传送
}
nread=ret;
int i;//检测有没有‘\n’字符,有则读取
for(i=0; i<nread,i++)
{
if(bufp[i]=='\n')
{
ret= readn(sockfd,bufp, i+1)
if(ret != i+1)//已经窥探到有i+1字符,如果没有则错误
exit(EXIT_FAILURE);
return ret;
}
}
//如果没有读到‘\n’,则将消息读入,直到最大包
nleft -= nread;
ret= readn(sockfd, bufp, nread);
if(ret != nread)//已经窥探到有nread个字符,如果r