0

我有以下代码,其中我正在使用 TCP 端口运行服务器。我需要派生并调用子例程来调用客户端,以便它们可以并行运行并与服务器连接。

到目前为止,我刚刚能够进行串行实现,其中调用是通过一个循环进行的,我似乎遇到了障碍,如果有人能不厌其烦地浏览代码,那就太好了引导我。

以下为主要内容。客户端子例程仅驻留在 client.c 中,并且似乎工作正常。如果需要,我也可以粘贴。

main(int argc, char *argv[])
{
  struct sockaddr_in manager, client;
  struct hostent *cp;
  int sockdescriptor, td;
  int len;
  char buf[BLEN];
  int j; 
  int n; 
  int num_nodes;
  pid_t pid;


  key_t key;
  int shmid;
  int *port_num;

  sockdescriptor = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

  memset((char *) &manager, 0, sizeof(struct sockaddr_in));
  manager.sin_family = AF_INET;
  manager.sin_addr.s_addr = INADDR_ANY;
  manager.sin_port = htons((u_short) 0); /* dynamically assigning port */

  bind(sockdescriptor, (struct sockaddr *) &manager, sizeof(struct sockaddr_in));

    len = sizeof(struct sockaddr_in);
    listen(sockdescriptor, QUELEN);

/***************************** Getting port by getsockname() **********************************/
/*                                                                                            */
/*                                                                                            */
  if(getsockname(sockdescriptor, (struct sockaddr *) &manager, &len) == -1){
    perror("getsockname failed!");
    return -1;
  }
/*                                                                                            */    
/*                                                                                            */
/**********************************************************************************************/  
    printf("manager port %d\n", (int) ntohs(manager.sin_port));


/********************************* Creating Shared Memory *************************************/
/*                                                                                            */    
/*                                                                                            */

    key = 1234;

    if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0){
        perror("shmget is broken!");
        exit(1);
    }

    if ((port_num = shmat(shmid, NULL, 0)) == (int *) -1){
        perror("shmat is broken!");
        exit(1);
    }

    *port_num = (int) ntohs(manager.sin_port);
/*                                                                                            */    
/*                                                                                            */
/**********************************************************************************************/  


   for(j = 0; j < num_nodes ; j++){
    if((pid = fork()) == 0){            // child process

          while(1) {

            len = sizeof(struct sockaddr_in);
            td = accept(sockdescriptor, (struct sockaddr *) &client, &len);

//                    close(sockdescriptor);            //closing listening socket

                cp = gethostbyaddr((char *) &client.sin_addr, sizeof(struct in_addr), AF_INET);
//              printf("Connected from %s\n", cp->h_name);

                client_num++;   
                    printf("client %d port %d\n",client_num, *port_num);

                sprintf(buf, "%d",nonce);
                send(td, buf, strlen(buf), 0);

                n = recv(td, buf, sizeof(buf), 0);

                printf("client %d says %s\n",client_num, buf);

                close(td); /* client request processed, close this client's socket */
                close(sockdescriptor);
                exit(0);
          } // end of while loop
    }
//  else if((pid = fork()) > 0){

    client_prog();  // Calls to this subroutine need to be via forked processes

//  close(td);
//  exit(0);

//  } // else if ends here

} // end of the for loop
4

1 回答 1

1

要拥有num_nodes客户,请执行以下操作:

for(j = 0; j<num_nodes; j++)
    if (fork() == 0) {
        close(sockdescriptor);
        client_prog();
        exit(0);
    }

然后让一个单独的进程处理每个客户端连接,以便多个客户端可以并行进行,我建议您将整个for循环替换为以下内容:

while(1) {
    td = accept(sockdescriptor, ...);
    client_num++;
    if (fork() == 0) {
        close(sockdescriptor);

        /* handle client interaction here */
        send(...) / receive(...)

        exit(0);
    } else {
        close(td);
    }
}

请注意,存在竞争条件:如果num_nodes大于 SOMAXCONN,则可能会丢弃连接。首先生成服务器进程并不能消除竞争条件。使用在叉前预先打开的管道,这种事情更安全。

于 2013-09-23T13:50:36.107 回答