通过TCP / IP发送文件

时间:2015-11-16 13:38:26

标签: c++ tcp client-server tcp-ip

我正在尝试使用Windows上的C ++程序通过TCP / IP发送文件。发送和接收工作正常。但在收到的文件中,每40个字符后会出现两个逗号。如果我发送例如:

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

接收的文件是:

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

以下是发送文件的服务器代码:

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;
}

以下是接收它的客户端代码:

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;

}

正如您所看到的,在收到的文件中会出现“,,”。知道怎么解决这个问题吗?

3 个答案:

答案 0 :(得分:1)

从各方面来看,看起来你有一个缓冲区溢出。请注意,不需要的字符出现在50个字节之后(而不是您在问题中所说的40个字节)。您的缓冲区长度为50个字符。

您不能在已读入的缓冲区上调用strlen(),因为strlen需要终止空字符才能工作。也就是说,你需要缓冲区为51个字符。

这可能不是唯一的问题,但肯定是其中的一部分。

答案 1 :(得分:0)

这里有很多问题。

  

以下是发送文件的服务器代码:

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)

send()部分应为send(sock, Sbuffer, n, 0)。这是潜在的问题。你的发送时间错误了。您还假设刚刚读取的数据实际上包含null,因此无法保证。 strlen()调用可能会超出缓冲区并导致未定义的行为。

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

memset()是不必要的。删除。

}

cout << "file sent" << endl;

return n;
}

这里你返回零。我没有看到这一点。

  

以下是接收它的客户端代码:

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);

再次memset()是不必要的:删除。

}

答案 2 :(得分:-1)

在您的客户端代码中,缓冲区实际上从未被设置为memsetted。这可能是问题所在。

第一次迭代假定&#39;缓冲区&#39;已经设置为&#39; \ 0&#39;此代码也是多余的 if (n < 0) { perror("recv()"); exit(errno); } 因为while(...)已经检查了这个并且在迭代结束时你在memset之前突破了循环并且通过这样做使整个循环变得冗余。请做memset以排除那些可能的罪魁祸首,你也可以申请这些建议,但这取决于你。

编辑: 通过使循环冗余,您可能无法接收所有数据。

编辑#2:编辑#2: 您也忽略了&#39; send&#39;的返回值。从msdn页面:

  

如果没有错误发生,send返回发送的总字节数,该字节数可能小于len参数中请求发送的数字。否则,返回值SOCKET_ERROR,并且可以通过调用WSAGetLastError来检索特定的错误代码。

因此可能会丢弃数据,因为它无法保证它会立即发送所有数据。

编辑#3 (很抱歉很多编辑) 您也不要在服务器代码中关闭文件句柄