简体   繁体   English

通过 TCP/IP 发送文件

[英]Sending files via TCP/IP

i'm trying to send a file via TCP/IP using a C++ program on windows.我正在尝试使用 Windows 上的 C++ 程序通过 TCP/IP 发送文件。 The send and the reception works fine.发送和接收工作正常。 but in the received file two commas appear after every 40 character.但在收到的文件中,每 40 个字符后出现两个逗号。 If I send for example :如果我发送例如:

123456789
123456789
123456789
123456789
123456789
123456789
23456789
123456789
123456789
123456789
123456789
123456789
123456789
123456789

The recepted file is :收到的文件是:

123456789
123456789
123456789
123456789
123456789
„123456789
123456789
123456789
123456789
123456789
„123456789
123456789
123456789
123456789

Here is the server code for sending a file :这是用于发送文件的服务器代码:

static int send_client_file(SOCKET sock, char *Sbuffer){

int n = 0;
char* f_name = "send.txt";
//char* f_name = "server.c";

cout << endl << "Waiting for the client message" << endl;
FILE *fp = fopen(f_name, "r");
if (fp == NULL)
{
    cout << "ERROR : File " << f_name << " not found ";
    perror("fopen()");
    exit(errno);
}

//bzero(Sbuffer, 50); // on vide le buffer d'envoie
memset(Sbuffer, 0, 50);
while((n = fread(Sbuffer, sizeof(char), 50, fp)) > 0)
{
    if((n = send(sock, Sbuffer, strlen(Sbuffer), 0)) < 0)
    {
        perror("send()");
        exit(errno);
    }
    memset(Sbuffer, 0, 50);
}

cout << "file sent" << endl;

return n;
}

And here is the client code to receive it :这是接收它的客户端代码:

int static recv_server_file(SOCKET sock, char *buffer){

int n = 0;
int m = 0;

cout << endl << "Receiving file from the server..." << endl;
char* f_name = "receive.txt";
FILE *fp = fopen(f_name, "a");
if (fp == NULL)
{
    cout << "ERROR : File " << f_name << "not found " << endl;
    perror("fopen()");
    exit(errno);
}

else {

while(n = recv(sock, buffer, Rbuffer_size, 0))
{
    if (n < 0)
    {
        perror("recv()");
        exit(errno);
    }
    m = fwrite(buffer, sizeof(char), n, fp);

    if(m < n)
    {
        cout << "File write failed." << endl;
        break;
    }

    break;
    memset(buffer, '/0', Rbuffer_size);
}
cout << "ok!" << endl;

fclose(fp);
}
cout << "The received data is : " << buffer << endl ;

return m;

}

As you can see, there is ",," which appears in the recepted file.如您所见,接收文件中出现了“,,”。 Any idea of how to resolve this ?知道如何解决这个问题吗?

By all appearances, it looks like you have a buffer overrun.从表面上看,您似乎有缓冲区溢出。 Note that the unwanted character occurs after 50 bytes (not 40 as you said in the question).请注意,不需要的字符出现在 50 个字节之后(而不是您在问题中所说的 40 个字节)。 Your buffer is 50 characters long.您的缓冲区长度为 50 个字符。

You cannot call strlen() on the buffer that you have read in, because strlen requires a terminating null character to work.您不能在读入的缓冲区上调用 strlen() ,因为 strlen 需要终止空字符才能工作。 That is, you'd need the buffer to be 51 characters.也就是说,您需要缓冲区为 51 个字符。

That may not be the only problem, but it is certainly part of it.这可能不是唯一的问题,但肯定是其中的一部分。

So many problems here.这里的问题太多了。

Here is the server code for sending a file:这是发送文件的服务器代码:

static int send_client_file(SOCKET sock, char *Sbuffer){

int n = 0;
char* f_name = "send.txt";
//char* f_name = "server.c";

cout << endl << "Waiting for the client message" << endl;
FILE *fp = fopen(f_name, "r");
if (fp == NULL)
{
    cout << "ERROR : File " << f_name << " not found ";
    perror("fopen()");
    exit(errno);
}

//bzero(Sbuffer, 50); // on vide le buffer d'envoie
memset(Sbuffer, 0, 50);

Unnecessary.不必要。 Remove.消除。

while((n = fread(Sbuffer, sizeof(char), 50, fp)) > 0)
{
    if((n = send(sock, Sbuffer, strlen(Sbuffer), 0)) < 0)

The send() part of that should be send(sock, Sbuffer, n, 0) .其中的send()部分应该是send(sock, Sbuffer, n, 0) This is the underlying problem.这是根本问题。 You are sending the wrong length.您发送的长度错误。 You are also assuming that the data just read actually contains a null, for which there is no guarantee.您还假设刚刚读取的数据实际上包含一个空值,对此无法保证。 The strlen() call could overrun the buffer and cause undefined behaviour. strlen()调用可能会溢出缓冲区并导致未定义的行为。

    {
        perror("send()");
        exit(errno);
    }
    memset(Sbuffer, 0, 50);

The memset() is unnecessary. memset()是不必要的。 Remove.消除。

}

cout << "file sent" << endl;

return n;
}

Here you are returning zero.在这里你返回零。 I don't see the point.我看不出重点。

And here is the client code to receive it :这是接收它的客户端代码:

int static recv_server_file(SOCKET sock, char *buffer){

int n = 0;
int m = 0;

cout << endl << "Receiving file from the server..." << endl;
char* f_name = "receive.txt";
FILE *fp = fopen(f_name, "a");
if (fp == NULL)
{
    cout << "ERROR : File " << f_name << "not found " << endl;
    perror("fopen()");
    exit(errno);
}

else {

while(n = recv(sock, buffer, Rbuffer_size, 0))
{
    if (n < 0)
    {
        perror("recv()");
        exit(errno);
    }
    m = fwrite(buffer, sizeof(char), n, fp);

    if(m < n)
    {
        cout << "File write failed." << endl;
        break;
    }

    break;
    memset(buffer, '/0', Rbuffer_size);

Again the memset() is unnecessary: remove.再次memset()是不必要的:删除。

}

In your client code the buffer is never actually memsetted.在您的客户端代码中,缓冲区实际上从未被设置过。 That could be the problem.那可能是问题所在。

The first iteration assumes that 'buffer' is already set to '\\0' also this code is redundant if (n < 0) { perror("recv()"); exit(errno); }第一次迭代假设 'buffer' 已经设置为 '\\0' 并且这个代码是多余的if (n < 0) { perror("recv()"); exit(errno); } if (n < 0) { perror("recv()"); exit(errno); } if (n < 0) { perror("recv()"); exit(errno); } Since the while(...) already checks that and in the end of the iteration you break out of the loop before you memset and by doing that making the entire loop redundant. if (n < 0) { perror("recv()"); exit(errno); }由于同时(......)已经将检查和你打破循环了你memset的前迭代结束,并通过这样做,使整个循环冗余。 Please do the memsets to rule out those possible culprits and you may apply the advices too, but that's up to you.请执行 memset 以排除那些可能的罪魁祸首,您也可以应用这些建议,但这取决于您。

EDIT: And by making the loop redundant you might not receive all the data.编辑:并且通过使循环冗余,您可能不会收到所有数据。

EDIT #2: Also you disregard the return value of 'send'.编辑#2:您也忽略了“发送”的返回值。 From the msdn page:从 msdn 页面:

If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent in the len parameter.如果没有发生错误,send 返回发送的总字节数,可以小于 len 参数中请求发送的字节数。 Otherwise, a value of SOCKET_ERROR is returned, and a specific error code can be retrieved by calling WSAGetLastError.否则返回 SOCKET_ERROR 值,调用 WSAGetLastError 可以检索到具体的错误代码。

So it might be that data gets discarded since there's no guarantee that it sends all data straight away.因此,数据可能会被丢弃,因为无法保证它会立即发送所有数据。

EDIT #3 (Sorry for many edits) Also you don't close your file handle in the server code编辑#3(对不起,很多编辑)你也没有在服务器代码中关闭你的文件句柄

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

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