C 收割机呼叫后服务器阻塞

C 收割机呼叫后服务器阻塞,c,tcpserver,C,Tcpserver,我当时正在使用TCP服务器,突然发生了一件非常奇怪的事情 当我与一个客户连接时,一切都会顺利进行。 当两个或多个客户端连接时,流量仍然正常。 但是,当任何一个客户端断开连接时,服务器就会在“收割者”调用之后立即阻塞。它就在那里等着 我在断开2个客户端中的1个并尝试重新连接时发现了这一点。重新连接的客户端根本不显示任何错误消息,它运行平稳。包可以发送到服务器,但它会堆积在服务器内部 另一方面,服务器挂在那里,等待一个特定的客户端断开连接。如果该客户端断开连接,服务器将恢复功能,执行其内部堆积的所有

我当时正在使用TCP服务器,突然发生了一件非常奇怪的事情

当我与一个客户连接时,一切都会顺利进行。
当两个或多个客户端连接时,流量仍然正常。
但是,当任何一个客户端断开连接时,服务器就会在“收割者”调用之后立即阻塞。它就在那里等着

我在断开2个客户端中的1个并尝试重新连接时发现了这一点。重新连接的客户端根本不显示任何错误消息,它运行平稳。包可以发送到服务器,但它会堆积在服务器内部

另一方面,服务器挂在那里,等待一个特定的客户端断开连接。如果该客户端断开连接,服务器将恢复功能,执行其内部堆积的所有请求

下面是我用于服务器结构的基本代码。
此代码还演示了上述问题。
谁能请,请,请指出是哪里出错的

void    reaper(int sig)
{
int status;

while (waitpid(-1, &status, WNOHANG) >= 0)
    /* empty */;
}


int     errexit(const char *format, ...)
{
    va_list args;

    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    exit(1);
}




int     errno;

unsigned short  portbase = 0;   /* port base, for non-root servers      */

int     passivesock(const char *service, const char *transport, int qlen)

{
    struct servent  *pse;   /* pointer to service information entry */
    struct protoent *ppe;   /* pointer to protocol information entry*/
    struct sockaddr_in sin; /* an Internet endpoint address         */
    int     s, type;        /* socket descriptor and socket type    */

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;

/* Map service name to port number */
    if ( pse = getservbyname(service, transport) )
            sin.sin_port = htons(ntohs((unsigned short)pse->s_port)
                    + portbase);
    else if ((sin.sin_port=htons((unsigned short)atoi(service))) == 0)
            errexit("can't get \"%s\" service entry\n", service);

/* Map protocol name to protocol number */
    if ( (ppe = getprotobyname(transport)) == 0)
            errexit("can't get \"%s\" protocol entry\n", transport);

/* Use protocol to choose a socket type */
    if (strcmp(transport, "udp") == 0)
            type = SOCK_DGRAM;
    else
            type = SOCK_STREAM;

/* Allocate a socket */
    s = socket(PF_INET, type, ppe->p_proto);
    if (s < 0)
            errexit("can't create socket: %s\n", strerror(s));

/* Bind the socket */
    if (errno=bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
            errexit("can't bind to %s port: %s\n", service,
                    strerror(errno));
    if (type == SOCK_STREAM && listen(s, qlen) < 0)
            errexit("can't listen on %s port: %s\n", service,
                    strerror(type));
    return s;
}

int     passiveTCP(const char *service, int qlen)
{
    return passivesock(service, "tcp", qlen);
}




#define QLEN              32    /* maximum connection queue length      */
#define BUFSIZE         4096


int     TCPechod(int fd);

int main(int argc, char *argv[])
{
    char    *service;      /* service name or port number  */
    struct  sockaddr_in fsin;       /* the address of a client      */
    unsigned int    alen;           /* length of client's address   */
    int     msock;                  /* master server socket         */
    int     ssock;                  /* slave server socket          */

    if (argc !=2)
            errexit("usage: %s port\n", argv[0]);

    service = argv[1];

    msock = passiveTCP(service, QLEN);

    (void) signal(SIGCHLD, reaper);

    while (1) {
            alen = sizeof(fsin);
            ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
            if (ssock < 0) {
                    if (errno == EINTR)
                            continue;
                    errexit("accept: %s\n", strerror(ssock));
            }
            printf("Accept connection %d from %s:%d\n", ssock, inet_ntoa(fsin.sin_addr), (int)ntohs(fsin.sin_port));
            switch (fork()){
            case 0:
                (void) close(msock);
                TCPechod(ssock);
                close(ssock);
                exit(0);
            default:
                close(ssock);
                break;
            case -1:
                errexit("fork: %s\n", strerror(errno));
            }              
    }
}


int     TCPechod(int fd)
{
    char    buf[BUFSIZE];
    int     cc;

    while (cc = read(fd, buf, sizeof(buf))) {
            if (cc < 0)
                    errexit("echo read: %s\n", strerror(cc));
            if (errno=write(fd, buf, cc) < 0)
                    errexit("echo write: %s\n", strerror(errno));
    }
    return 0;
}
void收割机(int-sig)
{
智力状态;
while(waitpid(-1,&status,WNOHANG)>=0)
/*空*/;
}
int errexit(常量字符*格式,…)
{
va_列表参数;
va_开始(参数,格式);
vfprintf(标准格式、格式、参数);
va_端(args);
出口(1);
}
int errno;
无符号短端口基=0;/*基本端口,用于非根服务器*/
int-passivesock(常量字符*服务,常量字符*传输,int-qlen)
{
指向服务信息条目的struct servent*pse;/*指针*/
struct protoent*ppe;/*指向协议信息条目的指针*/
sin中的struct sockaddr_;/*一个Internet端点地址*/
int s,type;/*套接字描述符和套接字类型*/
memset(&sin,0,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin\u addr.s\u addr=INADDR\u ANY;
/*将服务名称映射到端口号*/
if(pse=getservbyname(服务、传输))
sin.sin_port=htons(ntohs((无符号短)pse->s_port)
+港口基地);
如果((sin.sin_port=htons((无符号短)atoi(服务)))==0,则为else
errexit(“无法获取\%s\”服务条目\n”,服务);
/*将协议名称映射到协议编号*/
如果((ppe=getprotobyname(传输))==0)
errexit(“无法获取\%s\”协议条目\n”,传输);
/*使用协议选择套接字类型*/
如果(strcmp(传输,“udp”)==0)
类型=SOCK_DGRAM;
其他的
类型=SOCK_流;
/*分配套接字*/
s=插座(PF_INET,type,ppe->p_proto);
如果(s<0)
errexit(“无法创建套接字:%s\n”,strerror(s));
/*捆绑插座*/
if(errno=bind(s,(struct sockaddr*)&sin,sizeof(sin))<0
errexit(“无法绑定到%s端口:%s\n”,服务,
斯特雷罗(埃尔诺));
if(type==SOCK\u流&&listen(s,qlen)<0)
errexit(“无法侦听%s端口:%s\n”,服务,
斯特罗(型);
返回s;
}
int-passiveTCP(常量字符*服务,int-qlen)
{
返回被动时钟(服务,“tcp”,qlen);
}
#定义QLEN 32/*最大连接队列长度*/
#定义BUFSIZE 4096
int TCPechod(int fd);
int main(int argc,char*argv[])
{
char*服务;/*服务名称或端口号*/
fsin中的struct sockaddr_;/*客户端的地址*/
无符号int-alen;/*客户端地址的长度*/
int msock;/*主服务器套接字*/
int ssock;/*从服务器套接字*/
如果(argc!=2)
errexit(“用法:%s端口\n”,argv[0]);
服务=argv[1];
msock=passiveTCP(服务,QLEN);
(无效)信号(信号机,收割机);
而(1){
alen=sizeof(fsin);
ssock=accept(msock,(struct sockaddr*)和fsin,&alen);
如果(ssock<0){
如果(errno==EINTR)
继续;
errexit(“接受:%s\n”,strerror(ssock));
}
printf(“从%s接受连接%d:%d\n”,ssock,inet_ntoa(fsin.sin_addr),(int)ntohs(fsin.sin_端口));
开关(fork()){
案例0:
(无效)关闭(msock);
TCPechod(ssock);
关闭(ssock);
出口(0);
违约:
关闭(ssock);
打破
案例1:
errexit(“fork:%s\n”,strerror(errno));
}              
}
}
内部技术规范(内部fd)
{
字符buf[BUFSIZE];
int cc;
而(cc=read(fd,buf,sizeof(buf))){
if(cc<0)
errexit(“回显读取:%s\n”,strerror(cc));
如果(错误号=写入(fd、buf、cc)<0)
errexit(“回显写入:%s\n”,strerror(errno));
}
返回0;
}
如果您有任何意见,我们将不胜感激。

我提前向您表示感谢。

问题在于您如何调用waitpid,因为只有在发生错误时才离开while(如果发生错误,waitpid返回<0)。当您使用WNOHANG标志调用waitpid时,如果没有任何子进程终止,它将返回0(实际更改状态:已停止、已恢复或已终止)。尝试以下更正:

void reaper(int sig)
{
  int status;
  pid_t pid;
  while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
    printf("Proces PID: %d Hash Finished With Status: %d", pid, status);
  if (0 == pid) printf("No More Process Waiting");
  if (pid < 0) printf("An Error Ocurred");
}
void收割机(int-sig)
{
智力状态;
pid_t pid;
而((pid=waitpid(-1,&status,WNOHANG))>0)
printf(“进程PID:%d哈希已完成,状态:%d”,PID,状态);
如果(0==pid)printf(“不再有进程等待”);
如果(pid<0)printf(“出现错误”);
}
如果要使用等待,收割机功能必须类似于:

void reaper(int sig)
{
  int status;
  pid_t pid;
  pid = wait(&status); // Wait suspend the execution of the current process.
  if (pid > 0) printf("Proces PID: %d Hash Finished With Status: %d", pid, status);
  if (pid < 0) printf("An Error Ocurred");
}
void收割机(int-sig)
{
智力状态;
pid_t pid;
pid=wait(&status);//等待暂停当前进程的执行。
如果(pid>0)printf(“进程pid:%d哈希完成,状态:%d”,pid,状态);
如果(pid<0)printf(“出现错误”);
}

有关等待(2)的更多信息,请转到:

问题在于如何调用waitpi