【问题标题】:Client same socket descriptors客户端相同的套接字描述符
【发布时间】:2014-07-03 16:51:14
【问题描述】:

我有一个服务器-客户端系统(并发服务器)。我在不同的机器上有不同的客户端。我正在尝试向特定客户发送通知。但是,我有一个问题,因为客户端都具有相同的套接字描述符。在两台计算机上,客户端的套接字描述符为 3,服务器的 sd 为 5。有人可以告诉我如何识别这些不同的客户端以及为什么会发生这种情况?

int main(int argc, char *argv[]) {
    pid_t pid;
    int buff_size = 1024;
    char buff[buff_size];
    int listen_fd, client_conn;
    struct sockaddr_in serv_addr;
    int server_port = 5001;
    char remote_file[255];

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);

    if (listen_fd < 0) {
        perror("Socket cannot be opened");
        exit(1);
    }

    /*Turning off address checking in order to allow port numbers to be
      reused before the TIME_WAIT. Otherwise it will not be possible to bind
      in a very short time after the server has been shut down*/
    int on = 1;
    int status = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
                            (const char *) &on, sizeof(on));

    if (status == -1) {
        perror("Failed to Reuse Address on Binding");
    }

    // Initialise socket structure
    bzero((char *) &serv_addr, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY; // Accept connections from any address
    serv_addr.sin_port = htons(server_port);

    // Bind the host address
    if (bind(listen_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr))
        < 0) {
        perror("ERROR on binding");
        exit(1);
    }

    // Start listening for the clients, here process will
    // go in sleep mode and will wait for the incoming connection
    listen(listen_fd, 5);

    while (1) {
        //Accepting client connection
        client_conn = accept(listen_fd, (struct sockaddr *) NULL, NULL);

        if (client_conn < 0) {
            perror("Client was not accepted...");
            exit(1);
        }

        if ((pid = fork()) == 0) {
            close(listen_fd);
            bzero(buff, buff_size);

            while ((bytes_read = read(client_conn, buff, buff_size)) > 0) {

                fclose(file);
            }

        }

        //Terminating child process and closing socket
        close(client_conn);
        exit(0);

        bzero(buff, buff_size);

    }

    //parent process closing socket connection
    close(client_conn);
}

return 0;
}

【问题讨论】:

  • 这对客户来说很正常。套接字描述符是进程本地的,因此它们的 3 个描述符都是不同的。就像他们每个人都有自己的stdin FD 0。但是,如果您在一个服务器进程中为不同的并发客户端使用相同的套接字描述符,那么您就做错了。发布您的服务器代码。
  • 我插入了一些框架代码,也许你可以找出一个服务器进程中不同客户端的套接字描述符相同的问题
  • 为什么你的括号里有main()?最后还有一个额外的大括号。
  • 那是错误的巴玛 sry
  • 我仍然认为您没有正确复制代码。带有注释//Terminating child process 的代码在if 块之外,因此它在父子节点中运行。最后你有return 0,在main()函数之外。

标签: c linux client-server


【解决方案1】:

在服务器派生出一个孩子之后,它会执行close(client_conn)。当accept 为新连接分配一个套接字描述符时,它使用最低的关闭描述符。由于您之前关闭了套接字,因此它可以用于下一个进来的客户端。

这不是问题,因为连接由子进程管理。他们每个人都有自己的描述符5,并且互不干扰。

【讨论】:

  • 但是,我最后关闭了 clien_conn...我只在 fork() 之后关闭了 listen_fd
  • 您确实需要正确复制代码。您发布的代码中的块都搞砸了,所以我不知道您到底在做什么。
  • 您正在关闭子项中的listen_fd,您正在关闭父项中的client_conn。这是正确的做法。子进程不监听新连接,父进程也不对刚刚打开的新连接做任何事情。
  • 所以它正确吗? ...那么当我在双方都有相同的套接字描述符时,你认为我应该如何识别另一个客户端?非常感谢您的帮助。
  • 为什么需要识别它们?每个客户端都由不同的子进程管理。所以就他们而言,只有一个客户,他们没有什么需要区分的?
【解决方案2】:

您可以获得accept返回给您的客户端地址和端口。目前您正在传递一个空值

client_conn = accept(listen_fd, (struct sockaddr *) NULL, NULL);

但是只需添加几行,例如

struct sockaddr_in serv_addr, cli_addr;

int len = sizeof(cli_addr);
client_conn = accept(listen_fd, (struct sockaddr *) &cli_addr, &len);

并且您在 cli_addr.sin_addr.s_addr 和 cli_addr.sin_port 中有客户端信息。

你可以从fork的返回码中获取处理连接的子进程的pid。这应该会为您提供创建表所需的所有信息。

【讨论】:

    猜你喜欢
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多