Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 客户端完成消息传递后,服务器无法退出接受循环_C_Sockets_Tcp - Fatal编程技术网

C 客户端完成消息传递后,服务器无法退出接受循环

C 客户端完成消息传递后,服务器无法退出接受循环,c,sockets,tcp,C,Sockets,Tcp,使用fork创建客户端程序以读取多个文件并创建单独的套接字。然后,每个套接字将其读取的文件中的消息发送到服务器,服务器使用fork处理多个客户端。但是,服务器永远不会退出accept循环,因此即使客户端上的所有套接字都关闭了,它也不会终止 服务器: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h&g

使用fork创建客户端程序以读取多个文件并创建单独的套接字。然后,每个套接字将其读取的文件中的消息发送到服务器,服务器使用fork处理多个客户端。但是,服务器永远不会退出accept循环,因此即使客户端上的所有套接字都关闭了,它也不会终止

服务器:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>
#include "uthash.h" //Used for building hash map

#define PORT "3400"
#define HOST "localhost"
#define MAXDATASIZE 20
#define DEPARTMENT_LEN 2
#define BACKLOG 5



int main(void){
  int sockfd, rv, child, numBytes;
  int opt = 1;
  struct addrinfo hints, *servinfo, *p;
  struct sockaddr_storage their_addr; //connector's address information
  socklen_t sin_size;
  struct sigaction sa;

  char dept[MAXDATASIZE];
  double gpa;
  char dept_name[DEPARTMENT_LEN + 1];

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE;

  if((rv = getaddrinfo(HOST, PORT, &hints, &servinfo)) != 0){
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return 1;
  }

  //loop though all the results and bind to the first we can
  for(p = servinfo; p != NULL; p = p->ai_next){
    if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
      perror("server: socket");
      continue; //move to next available socket
    }

    //reuse port and supress address already in use warnings
    if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt)) == -1){
      perror("server: setsockopt");
      exit(1);
    }

    //Bind socket and local address
    if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1){
      close(sockfd);
      perror("server: bind");
      continue;
    }
    break;
  }

  if(p == NULL){
    fprintf(stderr, "server: failed to bind\n");
    return 1;
  }

  freeaddrinfo(servinfo); //free list structure

  //Listen to client
  if(listen(sockfd, BACKLOG) == -1){
    perror("server: listen");
    exit(1);
  }

  //Reap all dead processes
  sa.sa_handler = sigchild_handler;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_RESTART;
  if(sigaction(SIGCHLD, &sa, NULL) == -1){
    perror("sigaction");
    exit(1);
  }

  while(1){//accept() main loop
    sin_size = sizeof(their_addr);
    if((child = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1){
      perror("server: accept");
      continue;
    }

    if(!fork()){//this is the child process
      close(sockfd);
      while(1){
        if((numBytes = recv(child, dept, MAXDATASIZE, 0)) == -1){
          perror("server: recv");
          exit(1);
        }
        dept[numBytes] = '\0';
        if(strcmp(dept, ":exit") == 0){
          printf("%s\n", dept);
          break;
        }
        else{
          //printf("%s\n", dept);
          _parse_dept(dept, dept_name, &gpa);
          //printf("%s: %.1f\n", dept_name, gpa);
          _add_dept(dept_name, gpa);
          // _print_dept();
          bzero(dept_name, (int)strlen(dept_name));
          bzero(dept, (int)strlen(dept));
        }
      }//end while
      //_print_dept();
      printf("%d\n", 2);
      close(child);
      exit(0);
    }// end fork
    printf("%d\n", 3);
    close(child); //parent doesn't need this
  }
  printf("%d\n", 4);
  //_print_dept();
  // _delete_all();
  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“uthash.h”//用于构建哈希映射
#定义端口“3400”
#定义主机“localhost”
#定义MAXDATASIZE 20
#定义部门2
#定义待办事项5
内部主(空){
int sockfd,rv,child,numBytes;
int opt=1;
结构addrinfo提示,*servinfo,*p;
struct sockaddr\u存储它们的地址;//连接器的地址信息
袜子的大小;
struct-sigaction-sa;
char dept[MAXDATASIZE];
双gpa;
字符部门名称[部门名称+1];
memset(&hints,0,sizeof(hints));
hits.ai_family=AF_unsec;
hits.ai_socktype=SOCK_流;
hits.ai_flags=ai_被动;
if((rv=getaddrinfo(主机、端口、提示和服务信息))!=0){
fprintf(标准,“getaddrinfo:%s\n”,gai_strerror(rv));
返回1;
}
//循环遍历所有结果并绑定到第一个结果
for(p=servinfo;p!=NULL;p=p->ai_next){
if((sockfd=socket(p->ai_系列,p->ai_socktype,p->ai_协议))=-1){
perror(“服务器:套接字”);
继续;//移动到下一个可用套接字
}
//重用已在使用的端口和Superss地址警告
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR | SO_REUSEPORT,&opt,sizeof(opt))=-1){
perror(“服务器:setsockopt”);
出口(1);
}
//绑定套接字和本地地址
如果(绑定(sockfd,p->ai_addr,p->ai_addrlen)=-1){
关闭(sockfd);
perror(“服务器:绑定”);
持续
}
打破
}
if(p==NULL){
fprintf(stderr,“服务器:绑定失败\n”);
返回1;
}
freeaddrinfo(servinfo);//自由列表结构
//听取客户的意见
如果(侦听(sockfd,BACKLOG)=-1){
perror(“服务器:监听”);
出口(1);
}
//收获所有死亡的过程
sa.sa_handler=sigchild_handler;
sigemptyset(和sa.sa_面具);
sa.sa_标志=sa_重启;
if(sigaction(SIGCHLD,&sa,NULL)=-1){
佩罗尔(“sigaction”);
出口(1);
}
while(1){//accept()主循环
sin_size=sizeof(其地址);
if((child=accept(sockfd,(struct sockaddr*)及其地址和大小))=-1){
perror(“服务器:接受”);
持续
}
如果(!fork()){//这是子进程
关闭(sockfd);
而(1){
if((numBytes=recv(child,dept,MAXDATASIZE,0))=-1){
perror(“服务器:recv”);
出口(1);
}
部门[numBytes]='\0';
如果(strcmp(dept,“:exit”)==0){
printf(“%s\n”,部门);
打破
}
否则{
//printf(“%s\n”,部门);
_分析部门(部门、部门名称和gpa);
//printf(“%s:%.1f\n”,部门名称,gpa);
_添加部门(部门名称,gpa);
//_print_dept();
bzero(部门名称,(国际)斯特伦(部门名称);
bzero(部门)(内部)strlen(部门);;
}
}//结束时
//_打印部门();
printf(“%d\n”,2);
关闭(儿童);
出口(0);
}//端叉
printf(“%d\n”,3);
关闭(子项);//父项不需要这个
}
printf(“%d\n”,4);
//_打印部门();
//_删除_全部();
返回0;
}
客户:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/wait.h>

#define PORT "3400"
#define NO_DEPARTMENTS 3
#define LINE_SIZE 7
#define HOST "localhost"

//Global variable containing respective departments file name extensions
char * filenames[] = {"DepartmentA.txt", "DepartmentB.txt", "DepartmentC.txt"};
char * department_names[] = {"DepartmentA", "DepartmentB", "DepartmentC"};

int main(void){
  pid_t child_pid, wpid;
  int status = 0;
  for(int ii = 0; ii < NO_DEPARTMENTS; ii++){
    if((child_pid = fork()) == 0){
      int sockfd, rv;
      char dept_ip[INET6_ADDRSTRLEN]; //Department IP address
      unsigned int dept_port; //Department port
      struct addrinfo hints, *servinfo, *p;
      struct sockaddr_in my_addr;

      memset(&hints, 0, sizeof(hints));
      hints.ai_family = AF_UNSPEC;
      hints.ai_socktype = SOCK_STREAM;
      if((rv = getaddrinfo(HOST, PORT, &hints, &servinfo)) != 0){
        fprintf(stderr, "\ngetaddrinfo: %s\n", gai_strerror(rv));
        return 1;
      }

      //loop through all the results and connect to the first that we can find
      for(p = servinfo; p != NULL; p = p->ai_next){
        if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
          close(sockfd);
          perror("client: socket");
          continue;
        }

        if(connect(sockfd, p->ai_addr, p->ai_addrlen) == -1){
          close(sockfd);
          perror("client: connect");
          continue;
        }
        break;
      }
      if(p == NULL){
        fprintf(stderr, "client: failed to connect\n");
        return 1;
      }
      //1) Upon startup of Phase 1
      socklen_t len = sizeof(my_addr);
      getsockname(sockfd, (struct sockaddr *)&my_addr, &len);
      inet_ntop(AF_INET, &my_addr.sin_addr, dept_ip, sizeof(dept_ip));
      dept_port = ntohs(my_addr.sin_port);
      printf("<%s> has TCP port %d ", filenames[ii], dept_port);
      printf("and IP address %s for Phase 1\n", dept_ip);

      //2) Upon establishing a TCP connection to the admission office
      printf("<%s> is now connected to the admission office\n", filenames[ii]);


      //readfile and send contents to Addmissions office
      struct Node * fileContent = NULL;
      _readFile(&fileContent, filenames[ii]);

      struct Node * fileIter = fileContent;
      while(fileIter != NULL){
        sleep(3);
        send(sockfd, fileIter->dept, (int)strlen(fileIter->dept), 0);
        fileIter = fileIter->next;
      }
      sleep(3);
      char *ex = ":exit";
      send(sockfd, ex, (int)strlen(ex), 0);
      _freeFile(&fileContent);
      freeaddrinfo(servinfo); // free up list structure
      close(sockfd);
      exit(0); //exit for fork
    }
  }

  while ((wpid = wait(&status)) > 0);
  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义端口“3400”
#定义无需的部门3
#定义行大小为7
#定义主机“localhost”
//包含各个部门文件扩展名的全局变量
char*文件名[]={“DepartmentA.txt”、“DepartmentB.txt”、“DepartmentC.txt”};
char*部门名称[]={“部门A”、“部门B”、“部门C”};
内部主(空){
pid_t child_pid,wpid;
int status=0;
对于(int ii=0;ii<无部门;ii++){
if((child_pid=fork())==0){
int sockfd,rv;
char dept_ip[INET6_ADDRSTRLEN];//部门ip地址
未签名的int dept_port;//部门端口
结构addrinfo提示,*servinfo,*p;
我的地址中的结构sockaddr\u;
memset(&hints,0,sizeof(hints));
hits.ai_family=AF_unsec;
hits.ai_socktype=SOCK_流;
if((rv=getaddrinfo(主机、端口、提示和服务信息))!=0){
fprintf(标准格式,“\nGetAddressInfo:%s\n”,gai_strerror(rv));
返回1;
}
//循环浏览所有结果并连接到我们可以找到的第一个结果
for(p=servinfo;p!=NULL;p=p->ai_next){
if((sockfd=socket(p->ai_系列,p->ai_socktype,p->ai_协议))=-1){
关闭(sockfd);
perror(“客户端:套接字”);
持续
}
如果(连接(sockfd,p->ai_addr,p->ai_addrlen)=-1){
关闭(sockfd);
perror(“客户:连接”);
持续
}
打破
}
if(p==NULL){
fprintf(stderr,“客户端:连接失败\n”);
返回1;
}
//1) 第1阶段启动时
socklen\u t len=sizeof(我的地址);
getsockname(sockfd,(struct sockaddr*)和my_addr,&len);
inet_ntop(我的地址、我的地址、部门ip、大小(部门ip));
部门端口=ntohs(我的地址单端口);
printf(“具有TCP端口%d”,文件名[ii],部门端口);
printf(“第1阶段的IP地址%s”,部门IP);
//2) 建立与招生办公室的TCP连接后
printf(“现在已连接到入学办公室”,文件名[ii]);
//读取文件并将内容发送到Addmissions office
结构节点*fileContent=NULL;
_readFile(&fileContent,filename[ii]);
结构节点*fileIter=fileContent;
while(fileIter!=NULL){
睡眠(3);
发送(sockfd,文件管理器->部门,(内部)strlen(文件管理器->部门
if(counter > 0){
      close(child); //parent doesn't need this
      continue;
}else{
      wait(&status);
      printf("End of Phase 1 for the admission office\n");
      break;
}