【问题标题】:C: Pass socket connection via execlC:通过 execl 传递套接字连接
【发布时间】:2015-05-31 06:57:14
【问题描述】:

我正在尝试创建一个支持多个客户端的基本服务器。我希望主服务器连接到两个客户端,然后分叉并通过调用 execl 将客户端的文件描述符传递给另一个程序。两个客户端都连接到服务器并能够与之通信(通过向客户端询问用户名或句柄进行测试),但是当我尝试将客户端传递给第二个程序时(这意味着它之间的个人服务器客户端主持棋盘游戏比赛)当第二个程序尝试联系他们时,客户端没有显示输出,我很肯定这是我试图传递连接信息的方式。感谢您正确传递连接的任何帮助。

这是主服务器接受两个连接后的代码:

主服务器:注意。根据建议添加了额外的错误检查。

    if(fork() == 0){
        close(listener);
        int nBytes;
        char* playerOne[20];
        char* playerTwo[20];

        //Creates strings to hold file descriptor information for execl
        char connAscii[sizeof(int)];
        char connAscii2[sizeof(int)];
        snprintf(connAscii,sizeof(conn), "%d", conn);
        snprintf(connAscii2,sizeof(conn2), "%d", conn2);
        fprintf(stderr, "Int conn: %d, asciiConn: %s, backToInt: %d", conn, connAscii, atoi(connAscii));
        char *argf[2];
        argf[0] = connAscii; 
        argf[1] = connAscii2;


        //Send Handle Request to Connection 1
        nBytes = send(conn, handleRequest, sizeof(handleRequest),0);
        if(nBytes == -1){
            perror("send");
            exit(1);
        }
        //Receive Handle from Connection 1
        nBytes = recv(conn, playerOne, 20, 0);
        if(nBytes == -1){
            perror("recv");
            exit(1);
        }
        //Send Handle Request to Connection 2
        nBytes = send(conn2, handleRequest, sizeof(handleRequest),0);
        if(nBytes == -1){
            perror("send");
            exit(1);
        }
        //Receive Handle from Connection 2
        nBytes = recv(conn2, playerTwo, 20, 0);
        if(nBytes == -1){
            perror("recv");
            exit(1);
        }
        //Send Handle for Connection 2 to Connection 1
        nBytes = send(conn, playerTwo, sizeof(playerTwo),0);
        if(nBytes == -1){
            perror("send");
            exit(1);
        }
        //Send Handle for Connection 1 to Connection 2
        nBytes = send(conn2, playerOne, sizeof(playerOne),0);
        if(nBytes == -1){
            perror("send");
            exit(1);
        }

        //Passes file descriptors to nimMatch
        execl("nimMatch", "nimMatch", argf, (char *)0); 
    }

个人服务器(不同于主服务器的.c 文件):注意。添加调试语句

char greet[] = {"Hello players, please wait for match setup."};
    int main(int argc, char *argv[]) {
    int conn1 = atoi(argv[1]);
    int conn2 = atoi(argv[2]);
    int sent;
    fprintf(stderr, "Attempting connection\n");
    sent = send(conn1, greet,sizeof(greet),0);
    if(sent == -1){
        perror("send");
        exit(1);
    }
    return 0;
}

以及连接和匹配对手后的客户端代码:

printf("Your opponent is: %s\n\n Connecting to match server...",      otherHandle);
memset(&buf[0],0,sizeof(buf));
if ((numbytes = recv(sockfd, buf, 99, 0)) == -1) {  //should come from personal server
        perror("recv");
        exit(1);
    }
printf("From match server: %s\n", buf); 

如果需要更多代码,请告诉我,我知道客户端成功连接到服务器,并且在编译或运行时我没有收到任何错误。

来自 EJP 的建议答案可确保私有服务器接收正确的输入,但客户端似乎并未存储来自私有服务器的字符串。下面调整后的客户端代码表明客户端正在接收 64 字节但 buf 为空。

 printf("You're opponent is: %s\n\n Connecting to match server...", otherHandle);
memset(&buf[0],0,sizeof(buf));
numbytes = recv(sockfd, buf, 99, 0);
if (numbytes == -1) {
        perror("recv");
        exit(1);
    }
if(strlen(buf) < 1)
    fprintf(stderr, "No buffer input, found %d bytes\n", numbytes);
printf("From match server: %s\n", buf); 

【问题讨论】:

  • 您没有检查 send() 和 recv() 返回的值。如果不检查这些值,您将不知道实际发送或接收了多少字节,并且在不知道这一点的情况下,您的程序将无法可靠地工作。特别是您不应该认为 send() 和 recv() 会返回错误或您传入的字节数;它们可以(有时会)返回一个小于您传入的字节数的非负值,表示部分发送或接收。
  • @JeremyFriesner 谢谢我不知道,我是网络编程的新手,我会在我的代码中改变它。但是我不认为这是这个确切问题的一部分,因为客户端似乎没有从匹配服务器收到任何东西。但是谢谢你让我免了以后的头疼。
  • 那你就错了。第二个代码段不会阻塞。它将将该字符串传输到套接字发送缓冲区并立即返回。您确定文件描述符正在正确传递吗?全部,我的意思是全部,这里的系统调用需要错误检查。在您解决此问题并报告结果之前,进一步讨论此问题是没有意义的。不要将错误处理视为仅在代码运行后才添加的内容。从一开始就需要它来进行调试。
  • 叹息。 send() 是一个系统调用。 你必须检查它的返回值是否为 -1 并调用 perror(),就像你为 socket(), bind(), listen(), accept(), connect(), recv(),close(). 做的那样对它进行长度检查是不够的,实际上它在阻塞模式下毫无意义,因为它永远不会返回一个短计数。
  • 这一行:'execl("nimMatch", "nimMatch", argf, (char *)0)',根据手册页,应该是:'execl("nimMatch", "nimMatch" , argf[0],, argv[1], (char *)0)' 因为每个参数必须是指向字符串的指针,而不是指向字符串指针的指针

标签: c sockets network-programming client server


【解决方案1】:

您错误地将参数传递给execl()。它不需要参数数组,它需要一个可变参数列表。应该是

execl(path, connAscii, connAscii2, (char*)0);

【讨论】:

  • 谢谢,现在匹配服务器正确接收文件描述符,但客户端不显示匹配服务器的反馈,但是匹配服务器现在确实超过了发送。
  • 好吧,在客户端代码中它说 printf("From match server %s\n" ,buf) 它打印 From match server 但不是 buf
  • 应该是printf("From match server %.*s\n, numbytes, buf); 不需要memset()strlen() 测试无效:去掉。
  • 好的,我做了这些更改,但仍然没有显示来自 buf 的任何内容。我得到:你的对手是:kk 连接到匹配服务器...来自匹配服务器:
  • 因为这是一个不同的问题,并且您解决了我原来的问题,所以我接受了您的回答并在此处发布了新问题:stackoverflow.com/questions/29308845/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-07
  • 2023-03-11
  • 2020-09-23
  • 2023-04-08
  • 2018-02-18
  • 2013-02-12
  • 1970-01-01
相关资源
最近更新 更多