简体   繁体   English

在C for Linux中发送带套接字的文件

[英]Send a File with socket in C for Linux

I'm writing a small and simple server (in C language for Linux stations). 我正在编写一个小而简单的服务器(用于Linux工作站的C语言)。

A client requests a file to my server, my server asks this file to another server which sends it to my server. 客户端向我的服务器请求文件,我的服务器将此文件询问另一个服务器,该服务器将其发送到我的服务器。

My server should NOT receive ALL the file before sending it to the client BUT must send the bytes of the file so as they arrive. 我的服务器在将文件发送到客户端之前不应该收到所有文件但必须发送文件的字节以便它们到达。

This is an exercise in school so I can not dissociate myself from this requirement. 这是学校的一项练习,所以我不能脱离这个要求。

I have implemented the function explained below. 我已经实现了下面解释的功能。 The problem is that the client receives a non-deterministic number of bytes and NEVER the entire file. 问题是客户端收到的是非确定数量的字节,而不是整个文件。

int Recv_and_send_file (int socketa, int socketb, char *buffer, size_t file_size){

    size_t n;

    ssize_t nread;

    ssize_t nwritten;

    char c;

    for (n=1; n<file_size; n++)
    {        
            nread=recv(socketa, &c, 1, 0);

            if (nread == 1)
            {
                nwritten = send(socketb,&c,1,0);
            }
            else if (nread == 0)
            {
                *buffer = 0;
                return (-1); /* Errore */
            }
            else
                return (-1); /* Errore */
            }
    }
    *buffer = 0;
    return (n); 
}

Someone could kindly tell me where I'm wrong? 有人可以告诉我哪里错了?

Is it an stupid idea to change the values ​​SO_SNDBUF and SO_RCVBUF on both the server and the client? 在服务器和客户端上更改值SO_SNDBUF和SO_RCVBUF是一个愚蠢的想法吗?

Assuming the file_size is the total number of bytes you want to send, then your for loop will only send file_size - 1 bytes. 假设file_size是您要发送的总字节数,那么for循环将只发送file_size - 1个字节。 In other words, you are off by one. 换句话说,你是一个人。 Start from 0 instead to fix this: 0开始而不是修复此问题:

    for (n=0; n<file_size; n++)
    { //..

You capture the return value of send() , but you do not check to see if it was successful or not. 您捕获send()的返回值,但不检查它是否成功。

You are treating a 0 return value from recv() the same as an error. 您正在从recv()处理0返回值与错误相同。 Since you do not show what you do after returning -1 from your function, I don't know if this may be contributing to your problem or not. 由于您在从函数返回-1后没有显示您所执行的操作,因此我不知道这是否会导致您的问题。

Certain errors on send() and recv() are "soft", in that you are allowed to retry the operation for those particular errors. send()recv()上的某些错误是“软”的,因为您可以重试这些特定错误的操作。 One such error is EINTR , but check the documentation on your system to see if there are others. 一个这样的错误是EINTR ,但检查系统上的文档以查看是否还有其他文件。

In order to optimize performance and simplify your code, you can use splice()+pipes. 为了优化性能并简化代码,您可以使用splice()+管道。 Sendfile enables you to "forward" data between file descriptors, without the copy to user space. Sendfile使您可以在文件描述符之间“转发”数据,而无需将副本复制到用户空间。

Are you sure you have copied the correct code? 您确定已复制了正确的代码吗? That part as it is would not compile, there is a } in the last else which don't match with a corresponding {. 因为它不会编译,所以在最后一个中有一个}与相应的{不匹配}。

Also, how you get to know the file size? 另外,您如何知道文件大小? if it's send thru the socket as an integer, bear in mind the possible byte order of the source and destination machines. 如果它通过套接字作为整数发送,请记住源和目标机器的可能字节顺序。

Anyway, you are reading one byte at a time, you should improve it this way: 无论如何,你一次只读一个字节,你应该这样改进:

EDIT: use buffer and not the extra buff[2048]; 编辑:使用缓冲区而不是额外的buff [2048];

int Recv_and_send_file (int socketa, int socketb, char *buffer, size_t file_size){

    ssize_t nread;
    ssize_t nwritten;
    ssize_t bLeft=file_size;

    while (bLeft > 0)
    {
        nread=recv(socketa, buffer, bleft, 0);
        if (nread > 0)
        {
            nwritten = send(socketb, buffer, nread, 0);
            bLeft -= nread;
            buffer+=nread;
        }
        else if (nread == 0)
        {
            // I think this could raise a memory exception, read below
            *buffer = 0;
            return (-1); /* Errore */
        }
        else
        {
            return (-1); /* Errore */
        }
    }
    // If buffer is allocated with file_size bytes this one will raise a memory exception
    // *buffer = 0;
    return (file_size-bLeft);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM