我有以下代码,其中我使用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
答案 0 :(得分: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,则可能会断开连接。首先产生服务器进程并不能消除竞争条件。这种东西对于管道是更安全的,在叉子之前预先打开。