在 c 中的套接字编程中读取或写入后没有代码运行

No code runs after a read or a write in socket programming in c

我正在用 c.

制作服务器客户端程序

服务器启动先等待客户端,然后客户端"connects"。 客户端连接后,它等待用户输入,而服务器正在 运行ning read() 以从客户端获取输入。

这是主要问题。

在 while 循环发现换行符后,它将缓冲区中的数据从客户端发送到等待读取的服务器。服务器读取但是读取下面的任何代码都不能运行除非它与缓冲区有关。

所以如果代码是这样的 读取(socket_fd,浅黄色,sizeof(浅黄色)); printf("data from the client: %s",浅黄色); // 这一行在终端中将是 运行 printf("TESTING TESTING TESTING"); // 这一行永远不会被读取

客户端也一样。 在客户端执行 write() 之后,写入的任何代码都不会 运行。基本上这基本上是一个僵局,两个程序(我认为)都只是在等待另一个程序的输入。

我不知道这是为什么。也许它正在等待读取更多数据,但这并不能解释为什么它 运行 的代码打印缓冲区而不打印其他任何内容。

这是从客户端发送和接收数据的片段。服务器设置为 TCP

while(1){
    //wait for data from user
    bzero(buffer, 256);
    printf("Enter the string : ");
    n = 0;
    while ((buffer[n++] = getchar()) != '\n')
        ;
    write(sockfd, buffer, sizeof(buffer));
    printf("WE HERE");
    read(sockfd, buffer, sizeof(buffer));
    printf("READING THE DATA");
    printf("From Server : %s", buffer);
    if ((strncmp(buffer, "exit", 4)) == 0) {
        printf("Client Exit...\n");
        break;
    }
}

这是从客户端读取数据并提供响应的服务器代码。

while(1) {
    bzero(buffer, 256);


    //read the message from the client
    read(newsockfd, buffer, sizeof(buffer));
    printf("From the client: %s", buffer);

    printf("WORKING HERE BEFORE LOWER CASE [SERVER]");
    printf("the buffer again: %s", buffer);
    lower_string(buffer);
    printf("WORKING AFTER THE LOWER CASE [SERVER]");
    write(sockfd, buffer, sizeof(buffer));
    printf("WRITING TO THE CLIENT");

    if (strncmp("exit", buffer, 4) == 0) {
        printf("Server Exit...\n");
        break;
    }
    bzero(buffer, 256);
}

您的代码存在一些问题:

  1. 您没有在 printf() 语句的末尾放置换行符,这意味着打印的文本将不可见,直到标准输出缓冲区满到足以强制它是刷新到控制台。这可能会让您对程序的行为感到困惑,因为正在执行 printf() 语句,但您没有及时看到它们的输出。你应该做例如printf("WE HERE\n"); 而不是 printf("WE HERE");

  2. 您没有将 send()recv() 中的 return 值捕获到变量中,以便您可以检查它们 return 的值编辑并对其采取适当的行动。如果您不查看 return 值,您将不知道实际发送或接收了多少字节(它可能少于您要求发送或接收的字节数!)并且您不知道不知道是否发生了错误或 EOF 情况。

  3. 您应该知道 recv() 将阻塞,直到至少有一个字节的数据可用于放入您传入的缓冲区,同样,write() 可以阻塞直到至少有一个字节的传入缓冲区可以被网络堆栈使用。在某些情况下,这确实会导致死锁(例如,如果远程对等点从不发送任何数据,因为它被阻塞在 recv() 等待您先向它发送一些数据)。这个问题可以通过各种更高级的技术(例如超时、非阻塞或异步 I/O)来处理,但我不会在这里讨论这些。

  4. 将整个 256 字节数组置零,然后接收最多 256 字节意味着在您一次接收 256 字节数据的情况下,您的数组将不会以 NUL 结尾,并且如果您尝试将它用作 C 字符串(例如,将其传递给 printf("%s", buffer);,您将调用未定义的行为。您最好接收 sizeof(buf)-1 字节(并且如果您捕获 return recv() 的值,如第 2 点中所建议的,然后您可以在之后设置 buffer[numBytesReceived] = '[=20=]';,这是确保字符串以 NUL 结尾的比不必要地清除所有 256 更有效的方法字节)

  5. 请注意,您不能假设您将在单个 recv() 调用中 recv() 整个字符串。在这个玩具程序中不太可能发生(除非你的网络条件非常糟糕),但一般来说发件人有可能 send() 例如“123456789”和接收者的第一个 recv() 调用获得“1234”,然后第二个 recv() 调用获得“567”,然后第三个获得“89”,或字符串子集的任何其他组合.接收方保证按顺序接收所有字节,但不保证一次接收所有字节。生产级代码需要足够智能才能正确处理。