C 套接字编程:尝试使用 fork() 为新的客户端连接提供服务
C Socket Programming: Trying to serve new client connections using fork()
因此每个客户端连接都将由一个新的子进程提供服务。
现在,我有一个函数 generate_client() 可以创建一个客户端并给它一个随机 ID 号(返回给客户端)。
client_t generate_client()
{
client_t *client = malloc(sizeof(client_t));
client->clientID = randomClientIdGenerator(); < ----
client->entryIndexConstant = 0;
client->messageQueueIndex = 0;
client->readMsg = 0;
client->totalMessageSent = 0;
client->unReadMsg = 0;
client->status = CLIENT_INACTIVE;
return *client;
}
int randomClientIdGenerator()
{
int num = rand() % MAX_CLIENTS;
return num;
}
问题: 对于每个使用 fork() 的连接,子进程都是从父进程复制过来的,正如您在 客户端对象下面的实现中看到的具有相同客户端 ID 的文件被复制到子进程(至少这是我认为正在发生的事情)。
例如:使用终端1连接服务器生成客户端id 83,终端2连接也发送id 83。
/* bind the socket to the end point */
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind");
exit(1);
}
/* start listnening */
if (listen(sockfd, BACKLOG) == -1)
{
perror("listen");
exit(1);
}
while (1)
{
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1)
{
perror("accept.");
printf("\n...error: accept new_fd failed\n");
// continue;
}
printf("server: got connection from %s\n",
inet_ntoa(their_addr.sin_addr));
if (!fork())
{ /* this is the child process */
printf("\n-----------------------CHILD START ----------\n");
printf("\n child process id is %d. parent id is: %d\n", getpid(), getppid());
/* ***Server-Client Connected*** */
client_t client = generate_client();
printf("\n =>client id %d STATUS: %d\n", client.clientID, client.status);
if (client.clientID < -1)
{
perror("SERVER: failed to create client object (Max. 100 clients allowed)");
printf("SERVER: failed to create client object (Max. 100 clients allowed) \n");
exit(1);
// send response to client Cant accept connection
}
// Send: Welcome Message. ------------> SAME id of 83 is given to child process!!!
if (send(new_fd, &client.clientID, sizeof(int), 0) == -1)
{
perror("send");
printf("Error: Welcome message not sent to client \n");
}
}
}
我认为问题 是 fork() 中的 client_t client = generate_client();
.. 它生成从父进程复制过来的客户端,我该如何重新调用这可能在每个过程中?
这似乎与几个小时前发布的问题相同:
简答:
'rand'函数使用一个隐藏的'state'来生成下一个随机数。由于 parent 从不使用 rand,因此每个分叉 child 将获得相同的状态,并将生成相同的随机数序列。
几个可能的修复:
- 在 parent 中调用 rand(在分叉之前)。这将导致每个 child 以不同的状态开始。
- 在分叉前的 parent 中调用 rand,并保存 id 以供 child 使用。
- 使用 srand 为每个 child 设置随机数。
因此每个客户端连接都将由一个新的子进程提供服务。
现在,我有一个函数 generate_client() 可以创建一个客户端并给它一个随机 ID 号(返回给客户端)。
client_t generate_client()
{
client_t *client = malloc(sizeof(client_t));
client->clientID = randomClientIdGenerator(); < ----
client->entryIndexConstant = 0;
client->messageQueueIndex = 0;
client->readMsg = 0;
client->totalMessageSent = 0;
client->unReadMsg = 0;
client->status = CLIENT_INACTIVE;
return *client;
}
int randomClientIdGenerator()
{
int num = rand() % MAX_CLIENTS;
return num;
}
问题: 对于每个使用 fork() 的连接,子进程都是从父进程复制过来的,正如您在 客户端对象下面的实现中看到的具有相同客户端 ID 的文件被复制到子进程(至少这是我认为正在发生的事情)。
例如:使用终端1连接服务器生成客户端id 83,终端2连接也发送id 83。
/* bind the socket to the end point */
if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
{
perror("bind");
exit(1);
}
/* start listnening */
if (listen(sockfd, BACKLOG) == -1)
{
perror("listen");
exit(1);
}
while (1)
{
sin_size = sizeof(struct sockaddr_in);
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1)
{
perror("accept.");
printf("\n...error: accept new_fd failed\n");
// continue;
}
printf("server: got connection from %s\n",
inet_ntoa(their_addr.sin_addr));
if (!fork())
{ /* this is the child process */
printf("\n-----------------------CHILD START ----------\n");
printf("\n child process id is %d. parent id is: %d\n", getpid(), getppid());
/* ***Server-Client Connected*** */
client_t client = generate_client();
printf("\n =>client id %d STATUS: %d\n", client.clientID, client.status);
if (client.clientID < -1)
{
perror("SERVER: failed to create client object (Max. 100 clients allowed)");
printf("SERVER: failed to create client object (Max. 100 clients allowed) \n");
exit(1);
// send response to client Cant accept connection
}
// Send: Welcome Message. ------------> SAME id of 83 is given to child process!!!
if (send(new_fd, &client.clientID, sizeof(int), 0) == -1)
{
perror("send");
printf("Error: Welcome message not sent to client \n");
}
}
}
我认为问题 是 fork() 中的 client_t client = generate_client();
.. 它生成从父进程复制过来的客户端,我该如何重新调用这可能在每个过程中?
这似乎与几个小时前发布的问题相同:
简答:
'rand'函数使用一个隐藏的'state'来生成下一个随机数。由于 parent 从不使用 rand,因此每个分叉 child 将获得相同的状态,并将生成相同的随机数序列。
几个可能的修复:
- 在 parent 中调用 rand(在分叉之前)。这将导致每个 child 以不同的状态开始。
- 在分叉前的 parent 中调用 rand,并保存 id 以供 child 使用。
- 使用 srand 为每个 child 设置随机数。