僵尸进程是由于客户端退出连接后,服务器并不知道,还维持一个僵尸进程
使用signal消除
#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 <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*)bu