【问题标题】:How can I read an arbitrarily large file to a TCP Socket in C?如何在 C 中将任意大的文件读取到 TCP 套接字?
【发布时间】:2012-02-07 05:14:15
【问题描述】:

我只是在学习套接字编程,我正在尝试编写一个 echo 客户端,它从标准输入读取并写入套接字,然后将服务器响应从套接字读取到标准输出。问题是我不知道标准输入会有多长时间或服务器的响应会有多长时间。我尝试使用的代码如下(创建套接字和连接服务器被省略):

length = BUF_SIZE;
while (length == BUF_SIZE) {  // length will equal BUF_SIZE if buf is full, when length < BUF_SIZE we have reached an EOF                                 
   // Reads from STDIN to buf                                                                                                                              
   if ((length = read(STDIN_FILENO, buf, BUF_SIZE)) < 0){
     fprintf(stderr, "Error in reading from STDIN");
     return 4;
   }
   // Writes from buf to the socket                                                                                                                        
   if ((write(sock, buf, BUF_SIZE)) < 0){
     fprintf(stderr, "Error writing to socket");
     return 5;
   }
 }

if ((status = shutdown(sock, 1)) < 0){ // Shuts down socket from doing more receives                                                                      
   fprintf(stderr, "Error shutting down socket for writing");
   return 6;
}

length = BUF_SIZE; 
while (length == BUF_SIZE){
   // Read from socket to buf                                                                                                                              
   if ((length = read(sock, buf, BUF_SIZE)) < 0){
     fprintf(stderr, "Error reading from socket");
     return 7;
   }
   // Write from buf to STDOUT                                                                                                                             
   if ((write(STDOUT_FILENO, buf, BUF_SIZE)) < 0){
     fprintf(stderr, "Error writing to STDOUT");
     return 8;
   }
}

close(sock);
exit(0);

BUF_SIZE 定义为 100。当我运行我的程序时,程序通常会连接到服务器并发送正确的消息,但它写入 stdout 的内容要么什么都没有,要么是乱码。

我做错了什么?

【问题讨论】:

    标签: c sockets tcp client-server


    【解决方案1】:

    您的 while 循环只会在第一次完成。 read()/write() 只会返回他们实际读/写的数量,这很可能不等于 BUF_SIZE。假设您从套接字读取了 10 个字节,然后将 100 个字节写入标准输出 - 最后 90 个将是垃圾。

    这样的事情会让你更接近你想要的。

    while (1)
    {
        if ((length = read(STDIN_FILENO, buf, BUF_SIZE)) < 0)
        {
            fprintf(stderr, "Error in reading from STDIN");
            return 4;
        }
    
        if ((write(sock, buf, length)) < 0)
        {
            fprintf(stderr, "Error writing to socket");
            return 5;
        }
    
        if ((length = read(sock, buf, BUF_SIZE)) < 0)
        {
            fprintf(stderr, "Error reading from socket");
            return 7;
        }
    
        if ((write(STDOUT_FILENO, buf, length)) < 0)
        {
            fprintf(stderr, "Error writing to STDOUT");
            return 8;
        }
    }
    

    【讨论】:

    • 更不用说检查的不是从套接字读取了多少数据,而是在远程端关闭后读取返回-1的套接字上;标准输入相同。
    • 如果套接字中有超过 100 个字节,它会通过前 100 个字节,然后通过下一个 100 个和下一个 100 个字节,直到它到达 EOF 还是我这样想错了?
    • 是的,但这不是你的问题。这是相反的。无法保证 100 个字节会通过网络并在您进行读取时被 TCP 缓冲。如果更少,您将只获得缓冲区中的内容,并将返回长度。可能是 100 也可能是 4。
    • 基于此假设,大多数代码在较小的方面存在错误。要么你只需要读/写你得到的 要么 有一个已知的协议(例如,一个长度字节表示消息中有多少字节或消息分隔符,如换行符)并把你的读/循环写入,直到传输完整个消息。
    • 有什么方法可以让我测量套接字中消息的大小,以便我可以动态分配一个足够大的缓冲区来存储它?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-18
    • 2016-08-10
    • 2019-04-02
    • 2010-12-13
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多