在套接字上发送时出错错误的文件描述符

error bad file descriptor while send on socket

我正在尝试将数据从服务器子进程发送到客户端。 我将第一个客户端 fd 存储在 ids[0] 中,第二个存储在 ids[1] 中 然后我试图将数据从第一个子进程发送到另一个客户端,反之亦然。

我收到错误的文件描述符错误。

//ids are defined at the begining as follows
    int *ids = (int *) mmap(NULL,5*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
//accept is in a for loop...
    mysocket = accept(sock, NULL, NULL);
    printf("\nClient connected ...\n ");
    ids[i]=mysocket;
    i++;
    printf(" socket and id %d %d",mysocket,ids[i-1]);
    int pid = fork();
    if (pid == 0) {
        if (mysocket < 0) {
            perror("Error in accept");
            exit(1);
        }

    do {

        fflush(stdout);
        //clearing the bufffer
        //memset(&buf[0], 0, sizeof(buf));
        //memset(buf, sizeof(buf), '[=10=]');
        //reading message on the socket.
        if(i==1)
        if(send(ids[1], buf, 1024,0)==-1){
            perror("error in i=1");
                    printf("%d %d %d",mysocket,ids[0],ids[1]);
        }

        if(i==2) {
            if(send(ids[0], buf, 1024,0)==-1) {
                perror("error in i=2");
                printf("%d %d %d", mysocket, ids[0], ids[1]);
            }
        }

        if (strcmp(buf, "CLOSE") == 0) {
            close(mysocket);
            break;
        }

    } while (1);

我得到的错误: i=1 中的错误:错误的文件描述符 4 4 5

值 4 和 5 是 fds 并且已正确存储,我不会在任何地方关闭套接字。

您的代码格式错误,希望我能正确解释它。

ids[i]=mysocket;
i++;

如果 i0 那么 ids[0] 现在有效, ids[1] 仍然无效(即有一些看似有效但实际上无效的任意值)和i 现在是 1。使用 i==1 child 会遇到此代码(在正确格式化后):

    if(i==1)
        if(send(ids[1], buf, 1024,0)==-1){
            perror("error in i=1");
            printf("%d %d %d",mysocket,ids[0],ids[1]);
       }

如您所见,它使用了send(ids[1]...。但是正如上面对 i==1 的解释,只有 ids[0] 具有有效值,而 ids[1] 中的值无效。因此 send 失败 Bad file descriptor.

我的猜测是您假设在主进程中创建的文件描述符实际上在所有 child 进程中都有效,因为您正试图在主进程之间使用共享数组(具有 MAP_SHARED) childs和主人:

int *ids = (int *) mmap(NULL,5*sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);

但是这个假设是错误的。文件描述符不会传播到所有 child 进程中,而只会传播到新的 child 的 fork 上。这意味着您的第一个 child 仅在 fds[0] 中具有有效的文件描述符,而第二个 child 在 fds[0]fds[1] 中均具有有效的文件描述符。 由于共享数组,第一个 child 将在 fds[1] 中看到与第二个 child 相同的文件编号这一事实并不意味着该文件编号也相关联使用有效的 (in-kernel) 文件描述符。

请注意,在代码中实际记录代码的意图非常有用。这样其他人可以更好地理解您的代码,并且所有人(包括您)都可以更好地验证意图是否确实与实现相匹配。